[Scummvm-git-logs] scummvm master -> b6ee619b9ac153ec6f21540375386e09ef66486b
sev-
noreply at scummvm.org
Sun Jan 22 19:18:01 UTC 2023
This automated email contains information about 576 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
c71e5f6176 MM: Start of Might & Magic games engine that includes Xeen
f24debf602 MM: MM1: Skeleton engine class
6fedafac54 MM: MM1: Beginnings of events/ui manager
96fb461abb MM: MM1: Beginnings of screen viewer
49d5aad064 MM: MM1: Fixed screen decoding
1aaf783fc7 MM: MM1: Shifted screen decoder into a new ImageDecoder class
3aeb06b42e MM: Creating new combined mm data file for Xeen & MM1
fe3d35a58c MM: Created YAML file reader for representing string constants
027d7a5102 MM: Remove old xeen.ccs, change references to be mm.dat
97a0f7825d MM: MM1: Beginnings of text views
2aaceda632 MM: MM1: Somewhat improve text by using GUI console font
3718284f6f MM: MM1: Introduced focused view display
3a53a48989 MM: MM1: Beginnings of keyboard message dispatch
e2069e2f35 MM: MM1: Only redraw views when they mark themselves as changed
e64bedbde0 MM: MM1: Add name field to elements for later searches
92661fbd62 MM: MM1: identify views by name, allowing for easy switching views
595958e82f MM: MM1: Create Dialogs class as a container for all the dialogs
faf69883b9 MM: MM1: Remove uiParent parameter in view constructors
e5cc097f5d MM: MM1: Implementing view characters dialog
7b3cb3f12a MM: MM1: Adding display of character stats
15cf35f9d6 MM: MM1: Load roster, fixes to the view character dialog
bfb4b602a9 MM: MM1: Add loading roster inventories, display in character view
f35a80c6d2 MM: MM1: Add ability to delete characters
4ef63fdbaf MM: MM1: Implement renaming characters
493493a497 MM: MM1: Beginnings of create characters dialog
b0e79adf02 MM: MM1: Work on Create Characters dialog
3f31d825a5 MM: MM1: Remainder of character creation
29d4cd7a7e MM: MM1: Beginnings of Inn dialog
df961b6292 MM: MM1: Finished Inn dialog
44488c97d6 MM: MM1: Beginnings of in-game view
dbd06a89d7 MM: XEEN: Move XeenEngine methods from out of metaengine.cpp
28fe245365 MM: MM1: Adding keymapper set
a668109744 MM: MM1: Beginnings of QuickRef dialog
d9b59041ca MM: MM1: Creating data/ folder for game state related classes
be5e4e0153 MM: MM1: Added game state container class
1d4394a8dd MM: MM1: More implementation of QUickRef dialog
b81a1f3866 MM: MM1: Copy mode-specific keymaps logic from Ultima engine
9eae42cca4 MM: MM1: Hook up QuickRef dialog display to keybinder action
bb15af5dd8 MM: MM1: Handle QuickRef action inside QuickRef view itself
ffcda769b3 MM: MM1: Hook up action for viewing party members
3ad99de580 MM: MM1: Beginnings of Protect dialog
76a24b344e MM: MM1: Finished Protect dialog
31395720a6 MM: MM1: Beginnings of map classes
a88fc1a918 MM: MM1: Adding map overlay loading
def2d0ef29 MM: MM1: Add console with a dump_map command
cae78f2db8 MM: MM1: Added map_string debugger command
b6a3465b80 MM: MM1: Added placeholder map classes
2f7672f7db MM: MM1: Add the strings from map 0 to strings yml
d584fd7a7a MM: MM1: Figured out wall types part of map data
58d2396565 MM: MM1: More map data loading
95e8c8ab02 MM: MM1: Map loading method that triggers game view
ac9389c2b2 MM: MM1: The map getData method is actually for loading tiles
1505833b61 MM: MM1: Add town loading method
2d1f2b7831 MM: MM1: First wallpix tile being correctly decoded
6408139ea2 MM: MM1: Improve image decoder for tile loading
0708c63916 MM: MM1: Figured out map direction bitmasks and offsets
080866c484 MM: MM1: Beginnings of game view class
93a17c392a MM: MM1: Make the spells array a structure for easier access
5eb0e9d9a6 MM: MM1: In-progress 3d view drawing code
4b959dd7ae MM: MM1: 3d view is starting to render correctly
1dd472980c MM: MM1: Split game logic for 3d view into base class
f15dd4618a MM: MM1: Turning left and right re-renders view
96d1a1de39 MM: MM1: Dummy implementation for forward/backwards
a8b5ed0e7d MM: MM1: Fixes to 3d wall rendering
5012806724 MM: MM1: Implement support for element bounds
ffef7976f2 MM: MM1: Beginnings of enhanced mode
5f79a8b266 MM: MM1: Load Xeen UI background
48a9c9b93c MM: MM1: Change getSurface to return ManagedSurface
ed2d2d7713 MM: MM1: Different view area for Enhanced mode
a6f2260825 MM: MM1: Set up a simple palette to match the in-game colors
1e03780a76 MM: MM1: Tweak placement of 3d view in enhanced mode
6f640274c5 MM: MM1: Wall collision checks and proper map exit checks
f0c78a8ffb MM: MM1: Move checkPartyDead to Map class
b03f7f056b MM: MM1: Skeleton for special action methods in map 0
f6a1fe305a MM: MM1: Fix map 0 special cells check
82b0e0fa95 MM: MM1: Set up dummy party on startup
028e38d064 MM: MM1: Console commands pos and intangible
b3b95a65eb MM: MM1: Extracted font from executable
0db470e184 MM: MM1: Popup messages for obstructions
2fe7c8cc49 MM: MM1: Added stubbed Sound class
69dc7aac4d MM: MM1: Fixes to drawing view walls
6d674ca387 MM: MM1: Fix moving backwards
58f0b79b68 MM: MM1: Mostly implement bash
d06ce93568 MM: MM1: Display of party, beginnings of Order command
addfc3291b MM: MM1: Finished Order command
ccb355f62e MM: MM1: Added message info display
88cb46734c MM: MM1: Split off messages into their own file, improve Info message
ae5e45b17b MM: MM1: Implement shop signs message display
f2346f3ff0 MM: MM1: Refactor maps collection to be in maps.cpp
6ab8c299f9 MM: MM1: Implement support for Y/N messages
a815a3cbaa MM: MM1: Fixes for leaving Sorpigal
1c7c034ae5 MM: MM1: Beginnings of tavern, business display on-screen
e9680b0f50 MM: MM1: Creating separate subfolder for business views
bb55556921 MM: MM1: Common business rendering for Tavern
afb72630aa MM: MM1: Remainder of initial tavern display, leaving tavern
6df7a8c87f MM: MM1: More implementation of Tavern
7b9816c751 MM: MM1: Simply tavern message display
d38c12fde7 MM: MM1: Further implementing tavern
d0bc2a4796 MM: MM1: Workaround for 8Bh charcaters in strings
59c3982727 MM: MM1: Beginning of temple view
fd25f5e0a6 MM: MM1: Standardize Eulard sign string id to market
ca857e1d62 MM: MM1: Initial template display
dd233a50fa MM: MM1: Implement remainder of Temple
44cf0b55d1 MM: MM1: Added market view
22f8cde89a MM: MM1: Display of Xeen UI buttons in enhanced mode
4348a0b2d0 MM: XEEN: Fix startup crash
ccc0d5a872 MM: MM1: Add mouse cursor in enhanced mode
f10faec4d0 MM: MM1: Setting actions for the ui buttons
cc7588bf5a MM: MM1: Fix ui button press/release display
4ae422f19f MM: MM1: Beginnings of Training view
7fdea42900 MM: MM1: Implemented Statue view
366ab226dd MM: MM1: Updating message dispatches to use new send method
e7105ee603 MM: MM1: Make message msg methods protected
33c5fc3b24 MM: MM1: Added trapdoor
4787fae013 MM: MM1: Beginnings of Blacksmith
c33874faa6 MM: MM1: Implement leprechaun
cce5becae4 MM: MM1: Rename character max spell level
0e9226480e MM: MM1: Clarifying more character fields
aee5adc014 MM: MM1: Training calculations, display
7ed05692f3 MM: MM1: Implementing some of the training logic for increasing level
83209bc81d MM: MM1: Move training code to Character class
399fa65016 MM: MM1: Remainder of training
1db0b37b19 MM: MM1: Skeleton subviews for blacksmith buy/sell views
63117d1ab0 MM: MM1: Fixed shadowed field
3ebf0f8a8f MM: MM1: Move location data arrays to a new file
511a1eb829 MM: MM1: Implementing blacksmith buy weapons
8a5dcd4897 MM: MM1: Implementing blacksmith subviews
5016905f80 MM: MM1: Fix compiler warnings
1398295cf0 MM: MM1: Fix clashing town enums
3fb611c25c MM: MM1: In-progress implement sell items dialog
b627ba61ed MM: MM1: Add automap data to roster save file
cffa41c0e6 MM: MM1: Implement signing into inn
425f778f73 MM: MM1: Splitting up character display classes
0d642f71df MM: MM1: Beginnings of in-game character info
da1961795b MM: MM1: Implement gather gold in Character Info dialog
e4b88b84ff MM: MM1: Implemented Inventory class for backpack & equipped
b4ee049bd2 MM: MM1: Most of the character info equip item
3bbe7c32d4 MM: MM1: Remainder of equip item
5041dc79bc MM: MM1: Logic for remove item
722c610439 MM: MM1: Share function of character info
3f9f7b0f6f MM: MM1: Moved share method to new Party class
2164d978d0 MM: MM1: Created generic text entry view
395f5695db MM: MM1: Finished trading gems, gold, food
0253ded66e MM: MM1: Implementing most of item trade
502a2327fd MM: MM1: Merge id/v14 inventories into single Inventory class
ad11df142a MM: MM1: Finish item trading
dca3ae6b0d MM: MM1: Beginnings of spell casting
f4a59c9683 MM: MM1: Scroll window base class for enhanced mode
e6b233169a MM: MM1: Preparation for displaying text in character info
9f987817f4 MM: MM1: Implement loading of Xeen fonts
0a29bed97e MM: MM1: Enhanced mode text rendering working
0fe56f64bd MM: MM1: Set up attribute pairs, more of character info display
c69cf6cd95 MM: MM1: Finished title display in enhanced character info view
0c12139339 MM: MM1: Display of enhanced char info buttons text
90bb192ce1 MM: MM1: Added days suffix to food in char info
d1350f54dc MM: MM1: Added condition text to char info
12d69ae385 MM: MM1: Different text colors for conditions
c8f260ed03 MM: MM1: Skeleton encounter view class
c6afc8b9bd MM: MM1: Added blinking cursor to char info stats
283c1669d9 MM: MM1: Adding support for scroll views to display text
0a08b72e04 MM: MM1: Making text display it's own scroll subclass
392b4ff847 MM: MM1: Basic stat popups now showing
66e73672a8 MM: MM1: Show stat info by clicking on icons
6ad30c9094 MM: MM1: Stat info for gold, gems, food
5e8ce9f6cb MM: MM1: Message display in enhanced mode
be55e6e56f MM: MM1: Fix grocer text
bb518bcf16 MM: MM1: Word wrap strings in the game messages window
a8c666b3c6 MM: MM1: Set up so changing _bounds also changes _innerBounds
3cd64d79fa MM: MM1: Added messages sub-view for Y/N buttons
88edd92bf5 MM: MM1: Fix word-wrapping occurring exactly at end of line
d1eb30041f MM: MM1: Capitalize the word 'I' in messages
48a505a14d MM: MM1: Beginnings of enhanced locations views
b23a11c6ae MM: MM1: Close messages area before displaying location
5ec15a97eb MM: MM1: In progress Market location display
d36366d122 MM: MM1: Market location buttons
5016ae3975 MM: MM1: Fix redraw after releasing view buttons
d5db43209f MM: MM1: Cleanup of deprecated delay code
f14ec8f45a MM: MM1: Further implementation of Market location
37605e9150 MM: MM1: Correct text/icon offsets in Character Info view
45d6b97ac1 MM: MM1: Fix stat popups in character info view
27ff7e4663 MM: MM1: Switch to ScrollView as a base class for Location
c425b690eb MM: MM1: Fix display of market leaving messages
6b42ecb57f MM: MM1: Beginnings of temple location
d0817fc3a5 MM: MM1: Change char.cpp to character.cpp
b03e0feb5a MM: MM1: Further implementation of spelling casting
d2dd3253d6 MM: MM1: In progress new view for spell casting
639e6ddbcc MM: MM1: Further fixes for spell casting view
7fd9a03481 MM: MM1: Hide cursor after finishing text entry
75276b13f0 MM: MM1: Cast spell selection working
f9bc036099 MM: MM1: Light spell now working
3c0bf90c41 MM: MM1: Added stubs for all non-combat spells
06b6244a4d MM: MM1: Implementing cleric spells
453fab4fe6 MM: MM1: Display for spell failed
975b85cfef MM: MM1: Remaining cleric spells
4f61bb82dd MM: MM1: Starting wizard spells
bd2d8bc67e MM: MM1: Implement wizard levitate spell
b27f00dc53 MM: MM1: In progress implementing Fly spell destination selection
0a99c1ad78 MM: MM1: Adding a cast console command
b209a6a1df MM: MM1: Fix mapping spell level/num to spell index
ff46e2a56c MM: MM1: Fix display of Fly spell selection view
85b8b26c3a MM: MM1: Implemented some more wizard spells
183c9055bb MM: MM1: Adding rest view
662e6916c2 MM: MM1: Further rest implementation, added updateSP
ed63d19db9 MM: MM1: Implemented update58 method
a1dd06df3f MM: MM1: Finished Character::rest method
cdbe936eb9 MM: MM1: Hook up rest in-game action
eb18aaa157 MM: MM1: Added shelter spell
f370da260a MM: MM1: Adding teleport spell view
1913a5fa2e MM: MM1: Move CastSpell view to spells/ subfolder
4c7357bcfb MM: MM1: SpellView base class for spell dialogs
eaadd4025d MM: MM1: Teleport spell now working
6d164f04d7 MM: MM1: Implemented location spell view
58535f33d9 MM: MM1: Implemented Detect Magic spell and view
1fed7d3580 MM: MM1: Remaining wizard spell views
1b553ba1ab MM: MM1: Beginnings of encounter logic
80feff139b MM: MM1: Adding more encounter setup
e907ce5e06 MM: MM1: Remainder of encounter setup
a6562e60e1 MM: MM1: Beginnings of Encounter view
84f7c31ef5 MM: MM1: Added encounter console command
765a330f2b MM: MM1: Some fixes to encounter setup
443dfb2eed MM: MM1: Further encounter setup fixes
9c44cb4f0b MM: MM1: Extract the monster list into a resource file
eca200de31 MM: MM1: In progress experiments decoding monster images
7dd5f4f2a0 MM: MM1: Figured out confusion with Encounter _val11
49b1c776b5 MM: MM1: Monster images are now displaying
8c08892c03 MM: MM1: Starting to flesh out encounter view
1e3232ed25 MM: MM1: Implementing encounter options
f842f9e744 MM: MM1: More encounter options implementation
8ce5ba9a99 MM: MM1: Added more encounter view content
31ded9b30f MM: MM1: Field renamings for encounter manager
fb04ecadb9 MM: MM1: Fix remaining _val11 misunderstandings in encounter setup
0c58313608 MM: MM1: Fixed for encounter retreat option
33af429c51 MM: MM1: Beginnings of combat view
ad5c7997f7 MM: MM1: Move beginnings of combat data into separate class
8ec640a2dc MM: MM1: Implementing display of combat options
8bedce9ae2 MM: MM1: Added setupCanAttacks method
2e637f238a MM: MM1: Added writeHandicap method
ced1c79cc5 MM: MM1: Added setupHandicap method
11254c9e71 MM: MM1: Added the writeStaticContent method
a4992c9eb1 MM: MM1: Added writeRound, fixed writeHandicap
d882f2f019 MM: MM1: Added writePartyNumbers method
021528222f MM: MM1: Simplify the checkLeft/RightWall methods
15dfb0849f MM: MM1: Clean up encounter type, added optional parameter to console command
fa0b614e9c MM: MM1: Change map offsets to use DataOffset enum constants
61e5f45fa2 MM: MM1: Use map data constants for dataByte/dataWord
f151a7c9bb MM: MM1: Added writing combat monster list
e4959067e3 MM: MM1: Added writeParty method
9d1017a2ce MM: MM1: Starting to implement combat dialog main loop
08dbd97257 MM: MM1: Move just written combat loop stuff to common base class
3209b6cc72 MM: MM1: Added combat proc1 method
f8432a39fb MM: MM1: Change getRandomNumber to be 1 based by default
e26dff189e MM: MM1: In progress adding selectMonster method
d1b80934e4 MM: MM1: gcc compilation fixes
fa32e5623e MM: MM1: More gcc compilation fixes
84ccae5c76 MM: MM1: Added selectTreasure methods
e858af9196 MM: MM1: Adding rendering for monsters being defeated
d5b6d96a70 MM: MM1: Finished remainder of monsters defeated combat end
295461b2e6 MM: MM1: In progress support methods for next round code
9227a57ee5 MM: MM1: Added monsterChanges method
3face2321e MM: MM1: Added drawing of monster changes
19b933f93b MM: MM1: Started implementing monster actions
8dd3e3d84c MM: MM1: More implementation of monster fleeing
bdd433d745 MM: MM1: Change _monsterIndex to _monsterCount
654778837a MM: MM1: Further implementing combat
b93fc02377 MM: MM1: Beginnings of monster spell casting handler
ca2630c836 MM: MM1: Starting monster spells support methods
ad3fc28e6f MM: MM1: Further monster spell support methods
00de7b5e61 MM: MM1: Spell monsters elemental damage types
4f7c565d22 MM: MM1: Beginning to implement monster spells
969dbd8bcd MM: MM1: Implementing monster spells
5532c67cab MM: MM1: More monster spells
439611f707 MM: MM1: Remaining monster spell methods
43f1507bdc MM: MM1: Adding display for monster spell results
bb0114e6b2 MM: MM1: In progress attack code
c10035f064 MM: MM1: Method name renaming
e0b3883bcd MM: MM1: Combat uses the party copy, not the main one
ace0ae5d1f MM: MM1: Further attack code
bb1a1af1e0 MM: MM1: Remainder of character attack calculation and display
58d2f15553 MM: MM1: Added fight and shoot combat options
c7e9551cb1 MM: MM1: Added delay setting
fc5a8714f7 MM: MM1: Added Protect and QuickRef display from combat
9ec569d286 MM: MM1: In progress implementing character info use action
db2e6e15f9 MM: MM1: Clarified flags for allowing combat actions
ee3f96d38e MM: MM1: More implementing character user item
dcdef7a99f MM: MM1: Further implementing use action
4f97b6f36e MM: MM1: Hook up character info view to the combat use action
b5ca82cfdc MM: MM1: Add actions for viewing characters info to combat view
3a2203a464 MM: MM1: Properly handle character info use completion outside combat
b3d7755704 MM: MM1: Added a global flag for being in combat
9f9d9d5f7e MM: MM1: Non-combat spell messages match combat, but with stars
9a8dea21ec MM: MM1: Check for combat vs non-combat spells
da561aa2b7 MM: MM1: Move spells logic into game/ folder
4b08b3c816 MM: MM1: Start of combat spells
c77d3e531e MM: MM1: Skeleton classes for all the game maps
1c85a6e199 MM: MM1: Remove unneeded todos from map classes
22199d7546 MM: MM1: Created town map base class
9221ad76e5 MM: MM1: Map 1 has the first custom encounter
ddf7ca4f56 MM: MM1: Fix loading character roster
4f4130774b MM: MM1: Remainder of map 1 logic
dd423c184b MM: MM1: Add virtual destructors to base classes
53ae2cf070 MM: MM1: Add dumping of item list and loading from engine data
a8ad015fbe MM: MM1: Add missing breaks to switch statement
6ef8d409fa MM: MM1: Add missing file to module.mk
0a00d9878a MM: MM1: Fix movement
81496fa2b0 MM: MM1: Implemented most of map 2
22c8e97787 MM: MM1: Implemented map 2 resistances display
faa8ae1991 MM: MM1: Implemented map 3
b2eff4bf23 MM: MM1: In progress map 4, custom view for guards arresting
5ac771142c MM: MM1: Remainder of map 4 implemented
70ad0e7ae0 MM: MM1: Most of map 5 implemented
f793afbff0 MM: MM1: Remainder of map 5
0424ff5c57 MM: MM1: Added map 6
0800564280 MM: MM1: Added map 7
9215f84836 MM: MM1: Implemented access code view for map 8
313d468ff0 MM: MM1: Add remainder of map 8
9965b15877 MM: MM1: Implementing map 9
a99b52bbb1 MM: MM1: In progress map 10, added SoundMessage subclass
9d75df5ed3 MM: MM1: Change prior map classes to use new SoundMessage
7a8f045e7c MM: MM1: Support delay timeouts with callbacks in InfoMessage
c36fded8a0 MM: MM1: Remainder of map 10
2de1e45ab5 MM: MM1: Added volcano god view for map 11
c6662cfdcd MM: MM1: Finished map 11
210d48f921 MM: MM1: Added map 12
307223f54a MM: MM1: Added map 13
24196fc777 MM: MM1: Added map 14
62754ae602 MM: MM1: Added map 15
df97eb2a39 MM: MM1: Added map 16
cc7f562809 MM: MM1: Most of map 17
97bc7d57dc MM: MM1: Fix incorrect addAction calls
805aad5489 MM: MM1: Remainder of map 17
8692b23b56 MM: MM1: Most of map 18
6dfe1611ae MM: MM1: Added Won Game view, finishing map 18
5b37a16c4c MM: MM1: Added new base class for map views that have text entry
7e24562cb9 MM: MM1: Added Ice Princess view for map 19
88a63227b8 MM: MM1: Remainder of map 19
636bee1461 MM: MM1: Added most of map 20
d0486d5b88 MM: MM1: Made game update messages a method in the Map base class
128e81c216 MM: MM1: Compilation fix
b3ffa496ae MM: MM1: Fixes for item checks to check both equipped and backpack
d842c4da33 MM: MM1: Remainder of map 20
8fe5bd80ca MM: MM1: Added map 21
a587ae6e27 MM: MM1: Added map 22
1a5ddb0efe MM: MM1: Fixer compiler warnings
378a12922a MM: MM1: Added gypsy view for map 23
347233c82a MM: MM1: Add map 23
16b0c85daf MM: MM1: Added map 24
c6fc9a803d MM: MM1: Added map 25
09c3b7abad MM: MM1: Added map 26
9e705307ad MM: MM1: Added map 28
d0fccd35de MM: MM1: Added map 29
dbdd193ef9 MM: MM1: Added map 30
189b0e7ec1 MM: MM1: Added map 31
23d17a9e5a MM: MM1: Changed desert maps to use MapDesert base class
788d129bd0 MM: MM1: Added map 32
117e96141e MM: MM1: In progress map 33
5163e9bae6 MM: MM1: Remainder of map 33
69962c01fa MM: MM1: Added map 34
b149ce245c MM: MM1: Made common prisoner view class
80b9faec1c MM: MM1: Most of map 35, Inspectron code in progress
ee4a7759c8 MM: MM1: Remainder of map 35's Inspectron code
9a20265a5f MM: MM1: In progress map 36
985b617945 MM: MM1: Added map 36
b88d75d26b MM: MM1: Implement monster/figure drawing for maps 35 & 36
60512d223a MM: MM1: Added map 37
1dd7315fa4 MM: MM1: In progress map 38
3b9adfe37b MM: MM1: Add missing code to map 24
86a2c0b741 MM: MM1: Remainder of map 38
fa504a9d1f MM: MM1: Added map 39
58c98d2d4b MM: MM1: Added map 40
2242171342 MM: MM1: Added map 41
3458be7e49 MM: MM1: Added map 42
6bcc5cd66a MM: MM1: Added map 43
165c9c772f MM: MM1: Added map 44
04097ea070 MM: MM1: Added map 45
7fcdaa1125 MM: MM1: Added map 46
6406466488 MM: MM1: Fix treasure clearing on startup
284bed8afa MM: MM1: Added map 47
0e6b445c98 MM: MM1: Added map 48, fixed some answer entry views' rendering
f16eb6b245 MM: MM1: gcc compilation fixes
e3581b594a MM: MM1: More compilation fixes
7807085359 MM: MM1: Added map 49
731449d3be MM: MM1: Added map 50
59ca90fe4c MM: MM1: Added map 51
e8ebbe572d MM: MM1: Added map 52
5a4e052da5 MM: MM1: Added map 53
e801eb1047 MM: MM1: Added map 54. The last damn map.. finally
e0b9e7064c MM: MM1: Change DrawMonsterMessage to DrawGraphicMessage
a9303b908e MM: MM1: Beginnings of proper search view
322d01de64 MM: MM1: Refactor game view business names code to allow arbitrary text
cde86c909f MM: MM1: Fix display of search nothing, added treasure methods
f19e3781eb MM: MM1: Fix display of container type text in view area
5b96f31fcb MM: MM1: Fix display of search container graphic, map classes graphics
479411d0eb MM: MM1: More implementing Search dialog
771a642f3c MM: MM1: Shifted checkPartyDead method to Party class
c248428c6a MM: MM1: In progress Unlock view
8f56425493 MM: MM1: Fixes for unlocking view
cf7929fc80 MM: MM1: Fix maps mixing up map _walls and _states
9af8ddddb6 MM: MM1: In progress trap damage view
162e443890 MM: MM1: Remainder of trap logic
9ad34f4486 MM: MM1: Hook up Unlock to call Trap when trap triggered
e20bff29a0 MM: MM1: Fixes for trap triggered display
55f17ed039 MM: MM1: Give time to ready info messages when party dead
3492b7ab10 MM: MM1: Add Dead view
8c7db228f6 MM: MM1: Implement bash view
fdc0914e73 MM: MM1: Immediately process addAction/addKeypress calls
1b6238d5b5 MM: MM1: Fix selecting characters from Quick Ref view
a868a699dc MM: MM1: Fix Giant unfocus handler
ed0cf5b1ad MM: MM1: Fix switching character infos then pressing Escape
467b88f570 MM: MM1: Fix view area incorrectly showing some messages
dc11da0e20 MM: MM1: Cleanup of character info TODOs
71e4883db9 MM: MM1: Compilation fixes
75184f63a8 MM: MM1: Remove castUnknown for proper removeCharge
adf42ee7e3 MM: MM1: Rename remaining unknown character fields
673c1ff1e2 MM: MM1: Fix sign text in map 0
53dd26631b MM: MM1: Stub implementation for is key pressed, for maps
556c6e5fd8 MM: MM1: Fix writeString to handle color reversed characters
ae64653caa MM: MM1: Added a Roster update method
d418c2f930 MM: MM1: Repurpose unused last byte of character as portrait
1d9b52d78c MM: MM1: Added Character constructor
2b84d6db64 MM: MM1: Adding saving code
29646889fc MM: MM1: EXperiments using new saves format for MM1, old code for Xeen
4cf40ac22a MM: MM1: Further meta engine fixes for MM1 vs Xeen
754b2ca969 MM: MM1: Maps class cleanups
e32d1a6f6e MM: MM1: Further saving code hookup
0713cbee6e MM: MM1: Adding more data to savegames
1bf898525f MM: MM1: Added console command to list specials
299687eb72 MM: MM1: specials console cmd now includes codeless specials
3714770314 MM: MM1: Yet more changes to specials console command
8922bb134e MM: MM1: Added encounters console command to toggle encounters on/off
e4a2d7e782 MM: MM1: Add spells state info to savegames
d2dc840175 MM: MM1: Changed Spells to SpellsParty
5c90a590b7 MM: MM1: Set up SpellsParty so a dest monster can be specified
5bf2fb81c4 MM: MM1: Misc spell fixes
8e90a6f752 MM: MM1: Implemented turn undead spell
e1d14b2ed8 MM: MM1: Adding combat cleric spells
5883e84eb9 MM: MM1: More cleric combat spells
9a0bb8f35d MM: MM1: Starting spells' monster iteration code
ce459a5596 MM: MM1: Fleshing out iterateMonsters1
14a91ec61e MM: MM1: Finish iterateMonsters1
6166a646d3 MM: MM1: Implemented iterateMonsters2
63b879a607 MM: MM1: Add _timeoutCallback as an alias for _ynCallback for clarity
88449f23e1 MM: MM1: Added remaining cleric combat spells
7f7980e71f MM: MM1: Default delay and callback handler for combat spell result messages
11fa375fc2 MM: MM1: Starting wizard combat spells, identified multiple monster fields
22995c2987 MM: MM1: Shift displaySpellResult stub code to descendant view
519e254764 MM: MM1: More wizard combat spells
732762a597 MM: MM1: More wizard spells implemented
69dc6043d1 MM: MM1: Hook up duplication spell to it's custom view
22f4b8af84 MM: MM1: Finished search view
896a6ae9dd MM: MM1: Improve map classes setting of treasure
c9cc2d56cf MM: MM1: Further treasure cleanups
06c3754b7b MM: MM1: Add MonsterActions base class for monster actions logic
1195969603 MM: MM1: Rename MonsterActions class to MonsterTouch
95929db968 MM: MM1: Monster touch interface method in Combat class
b259ed6b2b MM: MM1: In progress monster attack logic
caa5347b2e MM: MM1: Shifting monster attack string display to view class
c8f03cf279 MM: MM1: Hooked up subtractDamage for monster attacks
277bd710a4 MM: MM1: Monsters selecting party target
f7864d7dbc MM: MM1: Monster shooting logic
6d89e52d17 MM: MM1: Fix combat party incapacitated check
ee05e6cb44 MM: MM1: Move several standalone arrays into Monster
d970e70cc5 MM: MM1: Move _arr4 into Monster as _checked
b8e432b394 MM: MM1: Moved combat character flags to Character
dc5e5b2a7b MM: MM1: Minor cleanup
d3a8ce091f MM: MM1: Implement in-combat retreat
1a7e3f4435 MM: MM1: Rename Character _arr3 to _checked
ba3acbbb70 MM: MM1: Display combat spell results
7301dcd15f MM: MM1: Hopefully properly implement monsterAdvances
f814fd681b MM: MM1: Fix _monsterP in monsterAdvances
ce6c698d2e MM: MM1: Hook up CastSpell view for in-combat spell casting
40c1082940 MM: MM1: More combat actions implemented
2014e4d24a MM: MM1: Fleshing out combat_val2 as _activeMonsterNum
f8547ef784 MM: MM1: Cleanup of title screen, EGA palette, and screen decoder
cb617fa82e MM: MM1: Implement scroll in alternating title screen
258bdacf60 MM: MM1: Implement title screen scene slideshow
3a5f3e5b19 MM: MM1: Set decoder palette indexes for first map
de92498b7f MM: MM1: Add green lines to game screen
5207f7da52 MM: MM1: Fix screen decoding for enhanced version
40743e9a86 MM: MM1: Go to Are You Ready screen from title screen
03f3adde3f MM: MM1: Start implementing proper per-map colors.
9b537e0b2f MM: MM1: Fix ladder string in map 11
08a3d46834 MM: MM1: Fix first view when loading a town on startup
88bcf16d32 MM: MM1: Fix dead display
4d9300ebbf MM: MM1: Fix display of blacksmith buy subviews
213632a62d MM: MM1: Fix display of staff in blacksmith buy weapons
508a478fa3 MM: MM1: Finish blacksmith selling item code
0893f3a2a5 MM: MM1: Fix character info view for sorcerers
6958216708 MM: MM1: Add enhanced minimap colors for exits and businesses
c9de1fb0f2 MM: MM1: Fixes to Gypsy in map 23
a2c9c9b110 MM: MM1: Draw new map position before triggering specials
71f22c251c MM: MM1: Tavern fixes
e9abe95d7e MM: MM1: Added endDelay method for expiring timeouts
b1b765b38a MM: MM1: Made endDelay return a bool for if delay was active
413b30ee9d MM: MM1: More use of endDelay
167d067366 MM: MM1: Map 23 fixes
0a036066a6 MM: MM1: Map changes fixes
d492eb5265 MM: MM1: Map fixes
5a17caf565 MM: MM1: Map 24 fixes
c77c2fdda7 MM: MM1: Map 20 fixexs
680b63087e MM: MM1: Map 43 fixes
185af7877c MM: MM1: Fixes for searching, and trap triggering in it
7b1d6e6f5b MM: MM1: Remove search debugging line
3ca92a0b1b MM: MM1: Fix checking into inns
33b138d3b5 MM: MM1: Map 1 fixes
66c994f8db MM: MM1: Fix colors for map 19
4a5b21f1a1 MM: MM1: Fixes for Ice Princess
7683524895 MM: MM1: Add missing access code view
b98e435e34 MM: MM1: Map 13 fixes
c0f6e0773a MM: MM1: Map 18 fixes
bae79d8206 MM: MM1: Prevent old text showing when going from large messages to normal
b8852e1df4 MM: MM1: Added a default section to every map
8296116d4d MM: MM1: Support id/section pair for console map selection
eee2ce23ca MM: MM1: More map fixes
3321c4397b MM: MM1: Do case insensitive answer comparisons
97db5ed0dd MM: MM1: Map 8 fixes
1c31a18d2e MM: MM1: More map fixes
6a40d6762a MM: MM1: Extra quit checks for main event loop
d9011fd241 MM: MM1: Allow timed game messages to close due to keypress
ffd370d4cf MM: MM1: More map fixes
f65b2eade1 MM: MM1: Further map fixes
75e5d978c7 MM: MM1: Fix desert map base class crash
391f7ab4f8 MM: MM1: More map fixes
8455b01891 MM: MM1: Fixed showing gems in search results
01870da12b MM: MM1: Further map fixes
16b25033db MM: MM1: Fix multiple maps' special loop
3cacb37d3b MM: MM1: Fix Inspectron and Hacker views
2f9c787e5f MM: MM1: Map fixes
17042d1f18 MM: MM1: Fixes for remaining maps
c1afda0570 MM: MM1: Desert maps will only be mappable if party has map
dbcf3e573c MM: MM1: Renamings for monster level
cf77d251f5 MM: MM1: Console encounter cmd now accepts monster num
0178c1b9b3 MM: MM1: Fix drawing monster graphic at start of encounters
6e88147ca5 MM: MM1: Fix clearing commands area at start of encounters
507a813342 MM: MM1: Fix script-based encounters setup
0ae511346e MM: MM1: Rename some monster fields
a3a9a280a4 MM: MM1: Rename encounter flag for better clarity
111408353c MM: MM1: Fix monster data list
5e09a089ec MM: MM1: Add level parameter to encounter console cmd
25ba84fe0d MM: MM1: Cleanup of encounter methods
75eec8a84e MM: MM1: Fixes for retreat and surrender in encounters
f04d6e4fd0 MM: MM1: Select a character by default on startup
262b93ec76 MM: MM1: Don't clear monster list when starting combat
13d94ffd94 MM: MM1: Simplify highlighting active combat char
4b0ea19e74 MM: MM1: Make separate monster list for combat vs encounter
155041d578 MM: MM1: Differentiate remaining combat monsters list from original _monsterList
91c997352a MM: MM1: Cleanup of post-combat treasure setup
770502487b MM: MM1: Change _remainingMonsters to be a Monster * array
830ef7f1f2 MM: MM1: Change hasFeature to use checkExtendedSaves function
cfb76d8cc2 MM: MM1: Change combat loop1 to selectMonster
c02226bff5 MM: MM1: Merge party/monsters turn selection methods into one
5209840a0f MM: MM1: Fix selecting correct combat char
cbbdff2d99 MM: MM1: Fix calculating party handicap
fbe6f34e11 MM: MM1: Fix Exchange combat option
8bbd2ed31a MM: MM1: Properly implement character stats view within combat
7e2ede96a1 MM: MM1: Fix retreating from combat
b7c1049c46 MM: MM1: Char targeted spells in combat use now global _combatParty
3aae2eb554 MM: MM1: Fix display of char attack messages
01d8d1abc7 MM: MM1: Strip off trailing spaces on monster names
91988d6f61 MM: MM1: Fix calculating monster AC and char damage amounts
373b6fac9c MM: MM1: Fixes for combat shooting
f1dd504365 MM: MM1: In combat allow keypresses to abort delay timeout
cf129a03a0 MM: MM1: Fix monster action check in combatLoop
b07b05c478 MM: MM1: Rename handicap fields
5e976fd2ce MM: MM1: Rename monster _field1E and enum
5e773537eb MM: MM1: Fix cancelling combat spell and then re-casting
b157a527d0 MM: MM1: Fix enter to cast text
9ede9e119f MM: MM1: Rendering of combat spell done
50a4e236ad MM: MM1: Fix showing non-combat spell only message
ce27924bc3 MM: MM1: Fix monster flees/wander rendering
f24cfbb048 MM: MM1: Add monster count parameter to encounter console cmd
545ae551fd MM: MM1: Clarify the variables for frontline monster attacker count
d49165fa52 MM: MM1: Code for removing dead monsters
6d50667455 MM: XEEN: Properly fix Swords monster list
62dd9be37f MM: MM1: Fix gcc warnings
316b65876a MM: MM1: Add missing override keywords
b6ee619b9a DISTS: Add placeholder for mm.dat file
Commit: c71e5f61763e4f43b3bb19eb87c7f972743c6abd
https://github.com/scummvm/scummvm/commit/c71e5f61763e4f43b3bb19eb87c7f972743c6abd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:40+01:00
Commit Message:
MM: Start of Might & Magic games engine that includes Xeen
Changed paths:
A engines/mm/POTFILES
A engines/mm/configure.engine
A engines/mm/credits.pl
A engines/mm/detection.cpp
A engines/mm/detection.h
A engines/mm/detection_tables.h
A engines/mm/metaengine.cpp
A engines/mm/mm.h
A engines/mm/module.mk
A engines/mm/xeen/character.cpp
A engines/mm/xeen/character.h
A engines/mm/xeen/combat.cpp
A engines/mm/xeen/combat.h
A engines/mm/xeen/cutscenes.cpp
A engines/mm/xeen/cutscenes.h
A engines/mm/xeen/debugger.cpp
A engines/mm/xeen/debugger.h
A engines/mm/xeen/dialogs/credits_screen.cpp
A engines/mm/xeen/dialogs/credits_screen.h
A engines/mm/xeen/dialogs/dialogs.cpp
A engines/mm/xeen/dialogs/dialogs.h
A engines/mm/xeen/dialogs/dialogs_awards.cpp
A engines/mm/xeen/dialogs/dialogs_awards.h
A engines/mm/xeen/dialogs/dialogs_char_info.cpp
A engines/mm/xeen/dialogs/dialogs_char_info.h
A engines/mm/xeen/dialogs/dialogs_control_panel.cpp
A engines/mm/xeen/dialogs/dialogs_control_panel.h
A engines/mm/xeen/dialogs/dialogs_copy_protection.cpp
A engines/mm/xeen/dialogs/dialogs_copy_protection.h
A engines/mm/xeen/dialogs/dialogs_create_char.cpp
A engines/mm/xeen/dialogs/dialogs_create_char.h
A engines/mm/xeen/dialogs/dialogs_difficulty.cpp
A engines/mm/xeen/dialogs/dialogs_difficulty.h
A engines/mm/xeen/dialogs/dialogs_dismiss.cpp
A engines/mm/xeen/dialogs/dialogs_dismiss.h
A engines/mm/xeen/dialogs/dialogs_exchange.cpp
A engines/mm/xeen/dialogs/dialogs_exchange.h
A engines/mm/xeen/dialogs/dialogs_info.cpp
A engines/mm/xeen/dialogs/dialogs_info.h
A engines/mm/xeen/dialogs/dialogs_input.cpp
A engines/mm/xeen/dialogs/dialogs_input.h
A engines/mm/xeen/dialogs/dialogs_items.cpp
A engines/mm/xeen/dialogs/dialogs_items.h
A engines/mm/xeen/dialogs/dialogs_map.cpp
A engines/mm/xeen/dialogs/dialogs_map.h
A engines/mm/xeen/dialogs/dialogs_message.cpp
A engines/mm/xeen/dialogs/dialogs_message.h
A engines/mm/xeen/dialogs/dialogs_party.cpp
A engines/mm/xeen/dialogs/dialogs_party.h
A engines/mm/xeen/dialogs/dialogs_query.cpp
A engines/mm/xeen/dialogs/dialogs_query.h
A engines/mm/xeen/dialogs/dialogs_quests.cpp
A engines/mm/xeen/dialogs/dialogs_quests.h
A engines/mm/xeen/dialogs/dialogs_quick_fight.cpp
A engines/mm/xeen/dialogs/dialogs_quick_fight.h
A engines/mm/xeen/dialogs/dialogs_quick_ref.cpp
A engines/mm/xeen/dialogs/dialogs_quick_ref.h
A engines/mm/xeen/dialogs/dialogs_spells.cpp
A engines/mm/xeen/dialogs/dialogs_spells.h
A engines/mm/xeen/dialogs/dialogs_whowill.cpp
A engines/mm/xeen/dialogs/dialogs_whowill.h
A engines/mm/xeen/dialogs/please_wait.cpp
A engines/mm/xeen/dialogs/please_wait.h
A engines/mm/xeen/events.cpp
A engines/mm/xeen/events.h
A engines/mm/xeen/files.cpp
A engines/mm/xeen/files.h
A engines/mm/xeen/font.cpp
A engines/mm/xeen/font.h
A engines/mm/xeen/interface.cpp
A engines/mm/xeen/interface.h
A engines/mm/xeen/interface_minimap.cpp
A engines/mm/xeen/interface_minimap.h
A engines/mm/xeen/interface_scene.cpp
A engines/mm/xeen/interface_scene.h
A engines/mm/xeen/item.cpp
A engines/mm/xeen/item.h
A engines/mm/xeen/locations.cpp
A engines/mm/xeen/locations.h
A engines/mm/xeen/map.cpp
A engines/mm/xeen/map.h
A engines/mm/xeen/party.cpp
A engines/mm/xeen/party.h
A engines/mm/xeen/patcher.cpp
A engines/mm/xeen/patcher.h
A engines/mm/xeen/resources.cpp
A engines/mm/xeen/resources.h
A engines/mm/xeen/saves.cpp
A engines/mm/xeen/saves.h
A engines/mm/xeen/screen.cpp
A engines/mm/xeen/screen.h
A engines/mm/xeen/scripts.cpp
A engines/mm/xeen/scripts.h
A engines/mm/xeen/sound.cpp
A engines/mm/xeen/sound.h
A engines/mm/xeen/sound_driver.cpp
A engines/mm/xeen/sound_driver.h
A engines/mm/xeen/sound_driver_adlib.cpp
A engines/mm/xeen/sound_driver_adlib.h
A engines/mm/xeen/spells.cpp
A engines/mm/xeen/spells.h
A engines/mm/xeen/sprites.cpp
A engines/mm/xeen/sprites.h
A engines/mm/xeen/subtitles.cpp
A engines/mm/xeen/subtitles.h
A engines/mm/xeen/swordsofxeen/swordsofxeen.cpp
A engines/mm/xeen/swordsofxeen/swordsofxeen.h
A engines/mm/xeen/swordsofxeen/swordsofxeen_menu.cpp
A engines/mm/xeen/swordsofxeen/swordsofxeen_menu.h
A engines/mm/xeen/window.cpp
A engines/mm/xeen/window.h
A engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
A engines/mm/xeen/worldofxeen/clouds_cutscenes.h
A engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp
A engines/mm/xeen/worldofxeen/darkside_cutscenes.h
A engines/mm/xeen/worldofxeen/worldofxeen.cpp
A engines/mm/xeen/worldofxeen/worldofxeen.h
A engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.cpp
A engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.h
A engines/mm/xeen/worldofxeen/worldofxeen_menu.cpp
A engines/mm/xeen/worldofxeen/worldofxeen_menu.h
A engines/mm/xeen/xeen.cpp
A engines/mm/xeen/xeen.h
A engines/mm/xeen/xsurface.cpp
A engines/mm/xeen/xsurface.h
R engines/xeen/character.cpp
R engines/xeen/character.h
R engines/xeen/combat.cpp
R engines/xeen/combat.h
R engines/xeen/configure.engine
R engines/xeen/credits.pl
R engines/xeen/cutscenes.cpp
R engines/xeen/cutscenes.h
R engines/xeen/debugger.cpp
R engines/xeen/debugger.h
R engines/xeen/detection.cpp
R engines/xeen/detection.h
R engines/xeen/detection_tables.h
R engines/xeen/dialogs/credits_screen.cpp
R engines/xeen/dialogs/credits_screen.h
R engines/xeen/dialogs/dialogs.cpp
R engines/xeen/dialogs/dialogs.h
R engines/xeen/dialogs/dialogs_awards.cpp
R engines/xeen/dialogs/dialogs_awards.h
R engines/xeen/dialogs/dialogs_char_info.cpp
R engines/xeen/dialogs/dialogs_char_info.h
R engines/xeen/dialogs/dialogs_control_panel.cpp
R engines/xeen/dialogs/dialogs_control_panel.h
R engines/xeen/dialogs/dialogs_copy_protection.cpp
R engines/xeen/dialogs/dialogs_copy_protection.h
R engines/xeen/dialogs/dialogs_create_char.cpp
R engines/xeen/dialogs/dialogs_create_char.h
R engines/xeen/dialogs/dialogs_difficulty.cpp
R engines/xeen/dialogs/dialogs_difficulty.h
R engines/xeen/dialogs/dialogs_dismiss.cpp
R engines/xeen/dialogs/dialogs_dismiss.h
R engines/xeen/dialogs/dialogs_exchange.cpp
R engines/xeen/dialogs/dialogs_exchange.h
R engines/xeen/dialogs/dialogs_info.cpp
R engines/xeen/dialogs/dialogs_info.h
R engines/xeen/dialogs/dialogs_input.cpp
R engines/xeen/dialogs/dialogs_input.h
R engines/xeen/dialogs/dialogs_items.cpp
R engines/xeen/dialogs/dialogs_items.h
R engines/xeen/dialogs/dialogs_map.cpp
R engines/xeen/dialogs/dialogs_map.h
R engines/xeen/dialogs/dialogs_message.cpp
R engines/xeen/dialogs/dialogs_message.h
R engines/xeen/dialogs/dialogs_party.cpp
R engines/xeen/dialogs/dialogs_party.h
R engines/xeen/dialogs/dialogs_query.cpp
R engines/xeen/dialogs/dialogs_query.h
R engines/xeen/dialogs/dialogs_quests.cpp
R engines/xeen/dialogs/dialogs_quests.h
R engines/xeen/dialogs/dialogs_quick_fight.cpp
R engines/xeen/dialogs/dialogs_quick_fight.h
R engines/xeen/dialogs/dialogs_quick_ref.cpp
R engines/xeen/dialogs/dialogs_quick_ref.h
R engines/xeen/dialogs/dialogs_spells.cpp
R engines/xeen/dialogs/dialogs_spells.h
R engines/xeen/dialogs/dialogs_whowill.cpp
R engines/xeen/dialogs/dialogs_whowill.h
R engines/xeen/dialogs/please_wait.cpp
R engines/xeen/dialogs/please_wait.h
R engines/xeen/events.cpp
R engines/xeen/events.h
R engines/xeen/files.cpp
R engines/xeen/files.h
R engines/xeen/font.cpp
R engines/xeen/font.h
R engines/xeen/interface.cpp
R engines/xeen/interface.h
R engines/xeen/interface_minimap.cpp
R engines/xeen/interface_minimap.h
R engines/xeen/interface_scene.cpp
R engines/xeen/interface_scene.h
R engines/xeen/item.cpp
R engines/xeen/item.h
R engines/xeen/locations.cpp
R engines/xeen/locations.h
R engines/xeen/map.cpp
R engines/xeen/map.h
R engines/xeen/metaengine.cpp
R engines/xeen/module.mk
R engines/xeen/party.cpp
R engines/xeen/party.h
R engines/xeen/patcher.cpp
R engines/xeen/patcher.h
R engines/xeen/resources.cpp
R engines/xeen/resources.h
R engines/xeen/saves.cpp
R engines/xeen/saves.h
R engines/xeen/screen.cpp
R engines/xeen/screen.h
R engines/xeen/scripts.cpp
R engines/xeen/scripts.h
R engines/xeen/sound.cpp
R engines/xeen/sound.h
R engines/xeen/sound_driver.cpp
R engines/xeen/sound_driver.h
R engines/xeen/sound_driver_adlib.cpp
R engines/xeen/sound_driver_adlib.h
R engines/xeen/spells.cpp
R engines/xeen/spells.h
R engines/xeen/sprites.cpp
R engines/xeen/sprites.h
R engines/xeen/subtitles.cpp
R engines/xeen/subtitles.h
R engines/xeen/swordsofxeen/swordsofxeen.cpp
R engines/xeen/swordsofxeen/swordsofxeen.h
R engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
R engines/xeen/swordsofxeen/swordsofxeen_menu.h
R engines/xeen/window.cpp
R engines/xeen/window.h
R engines/xeen/worldofxeen/clouds_cutscenes.cpp
R engines/xeen/worldofxeen/clouds_cutscenes.h
R engines/xeen/worldofxeen/darkside_cutscenes.cpp
R engines/xeen/worldofxeen/darkside_cutscenes.h
R engines/xeen/worldofxeen/worldofxeen.cpp
R engines/xeen/worldofxeen/worldofxeen.h
R engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp
R engines/xeen/worldofxeen/worldofxeen_cutscenes.h
R engines/xeen/worldofxeen/worldofxeen_menu.cpp
R engines/xeen/worldofxeen/worldofxeen_menu.h
R engines/xeen/xeen.cpp
R engines/xeen/xeen.h
R engines/xeen/xsurface.cpp
R engines/xeen/xsurface.h
diff --git a/engines/mm/POTFILES b/engines/mm/POTFILES
new file mode 100644
index 00000000000..5add393836d
--- /dev/null
+++ b/engines/mm/POTFILES
@@ -0,0 +1,2 @@
+engines/mm/detection.cpp
+engines/mm/xeen/saves.cpp
diff --git a/engines/xeen/configure.engine b/engines/mm/configure.engine
similarity index 79%
rename from engines/xeen/configure.engine
rename to engines/mm/configure.engine
index 6907bde9820..98e48a9ede9 100644
--- a/engines/xeen/configure.engine
+++ b/engines/mm/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine xeen "World of Xeen" yes
+add_engine mm "Might and Magic" yes
diff --git a/engines/xeen/credits.pl b/engines/mm/credits.pl
similarity index 54%
rename from engines/xeen/credits.pl
rename to engines/mm/credits.pl
index ff07c4694de..f6c0f6cd617 100644
--- a/engines/xeen/credits.pl
+++ b/engines/mm/credits.pl
@@ -1,6 +1,6 @@
begin_section("Xeen");
add_person("Paul Gilbert", "dreammaster", "");
add_person("Benoit Pierre", "benoit-pierre", "");
- add_person("David Goldsmith", "WizardStan", "(analysis)");
- add_person("Matt Taylor", "", "(analysis)");
+ add_person("David Goldsmith", "WizardStan", "(Xeen analysis)");
+ add_person("Matt Taylor", "", "(Xeen analysis)");
end_section();
diff --git a/engines/xeen/detection.cpp b/engines/mm/detection.cpp
similarity index 60%
rename from engines/xeen/detection.cpp
rename to engines/mm/detection.cpp
index 70c2bd07a9e..856fd253f1e 100644
--- a/engines/xeen/detection.cpp
+++ b/engines/mm/detection.cpp
@@ -21,11 +21,12 @@
#include "base/plugins.h"
#include "engines/advancedDetector.h"
+#include "common/translation.h"
+#include "mm/detection.h"
+#include "mm/mm.h"
-#include "xeen/detection.h"
-#include "xeen/xeen.h"
-
-static const PlainGameDescriptor XeenGames[] = {
+static const PlainGameDescriptor MIGHT_AND_MAGIC_GAMES[] = {
+ { "mm1", "Might and Magic: Book One - Secret of the Inner Sanctum"},
{ "cloudsofxeen", "Might and Magic IV: Clouds of Xeen" },
{ "darksideofxeen", "Might and Magic V: Darkside of Xeen" },
{ "worldofxeen", "Might and Magic: World of Xeen" },
@@ -33,38 +34,38 @@ static const PlainGameDescriptor XeenGames[] = {
{0, 0}
};
-static const DebugChannelDef debugFlagList[] = {
- {Xeen::kDebugPath, "Path", "Pathfinding debug level"},
- {Xeen::kDebugScripts, "scripts", "Game scripts"},
- {Xeen::kDebugGraphics, "graphics", "Graphics handling"},
- {Xeen::kDebugSound, "sound", "Sound processing"},
+static const DebugChannelDef DEBUG_FLAT_LIST[] = {
+ { MM::kDebugPath, "Path", "Pathfinding debug level" },
+ { MM::kDebugScripts, "scripts", "Game scripts" },
+ { MM::kDebugGraphics, "graphics", "Graphics handling" },
+ { MM::kDebugSound, "sound", "Sound processing" },
DEBUG_CHANNEL_END
};
-#include "xeen/detection_tables.h"
+#include "mm/detection_tables.h"
-class XeenMetaEngineDetection : public AdvancedMetaEngineDetection {
+class MMMetaEngineDetection : public AdvancedMetaEngineDetection {
public:
- XeenMetaEngineDetection() : AdvancedMetaEngineDetection(Xeen::gameDescriptions, sizeof(Xeen::XeenGameDescription),
- XeenGames) {
+ MMMetaEngineDetection() : AdvancedMetaEngineDetection(MM::GAME_DESCRIPTIONS,
+ sizeof(MM::MightAndMagicGameDescription), MIGHT_AND_MAGIC_GAMES) {
_maxScanDepth = 3;
}
const char *getName() const override {
- return "xeen";
+ return "mm";
}
const char *getEngineName() const override {
- return "Xeen";
+ return "Might & Magic";
}
const char *getOriginalCopyright() const override {
- return "Xeen (C) 1992-1993 New World Computing, Inc.";
+ return "Might And Magic games (C) 1986-1993 New World Computing, Inc.";
}
const DebugChannelDef *getDebugChannels() const override {
- return debugFlagList;
+ return DEBUG_FLAT_LIST;
}
};
-REGISTER_PLUGIN_STATIC(XEEN_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, XeenMetaEngineDetection);
+REGISTER_PLUGIN_STATIC(MM_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, MMMetaEngineDetection);
diff --git a/engines/xeen/detection.h b/engines/mm/detection.h
similarity index 82%
rename from engines/xeen/detection.h
rename to engines/mm/detection.h
index d2b2aaa39c7..05a7cfcff1b 100644
--- a/engines/xeen/detection.h
+++ b/engines/mm/detection.h
@@ -19,21 +19,22 @@
*
*/
-#ifndef XEEN_DETECTION_H
-#define XEEN_DETECTION_H
+#ifndef MM_DETECTION_H
+#define MM_DETECTION_H
#include "engines/advancedDetector.h"
-namespace Xeen {
+namespace MM {
enum {
- GType_Clouds = 1,
- GType_DarkSide = 2,
- GType_WorldOfXeen = 3,
- GType_Swords = 4
+ GType_MightAndMagic1,
+ GType_Clouds,
+ GType_DarkSide,
+ GType_WorldOfXeen,
+ GType_Swords
};
-struct XeenGameDescription {
+struct MightAndMagicGameDescription {
ADGameDescription desc;
int gameID;
@@ -43,6 +44,6 @@ struct XeenGameDescription {
#define GAMEOPTION_SHOW_ITEM_COSTS GUIO_GAMEOPTIONS1
#define GAMEOPTION_DURABLE_ARMOR GUIO_GAMEOPTIONS2
-} // End of namespace Xeen
+} // namespace MM
-#endif // XEEN_DETECTION_H
+#endif // MM_DETECTION_H
diff --git a/engines/xeen/detection_tables.h b/engines/mm/detection_tables.h
similarity index 98%
rename from engines/xeen/detection_tables.h
rename to engines/mm/detection_tables.h
index 6ee7f95c738..afaa96f8e33 100644
--- a/engines/xeen/detection_tables.h
+++ b/engines/mm/detection_tables.h
@@ -19,9 +19,9 @@
*
*/
-namespace Xeen {
+namespace MM {
-static const XeenGameDescription gameDescriptions[] = {
+static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
{
// World of Xeen
{
@@ -294,4 +294,4 @@ static const XeenGameDescription gameDescriptions[] = {
{ AD_TABLE_END_MARKER, 0, 0 }
};
-} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/metaengine.cpp b/engines/mm/metaengine.cpp
similarity index 68%
rename from engines/xeen/metaengine.cpp
rename to engines/mm/metaengine.cpp
index 12cc9f08ad0..cb6f599f258 100644
--- a/engines/xeen/metaengine.cpp
+++ b/engines/mm/metaengine.cpp
@@ -19,49 +19,22 @@
*
*/
-#include "xeen/xeen.h"
-#include "xeen/worldofxeen/worldofxeen.h"
-#include "xeen/swordsofxeen/swordsofxeen.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/worldofxeen/worldofxeen.h"
+#include "mm/xeen/swordsofxeen/swordsofxeen.h"
#include "base/plugins.h"
#include "common/savefile.h"
#include "engines/advancedDetector.h"
#include "common/system.h"
#include "common/translation.h"
-#include "xeen/detection.h"
+#include "mm/detection.h"
#define MAX_SAVES 99
+namespace MM {
namespace Xeen {
-static const ADExtraGuiOptionsMap optionsList[] = {
- {
- GAMEOPTION_SHOW_ITEM_COSTS,
- {
- _s("Show item costs in standard inventory mode"),
- _s("Shows item costs in standard inventory mode, allowing the value of items to be compared"),
- "ShowItemCosts",
- false,
- 0,
- 0
- }
- },
-
- {
- GAMEOPTION_DURABLE_ARMOR,
- {
- _s("More durable armor"),
- _s("Armor won't break until character is at -80HP, rather than merely -10HP"),
- "DurableArmor",
- false,
- 0,
- 0
- }
- },
-
- AD_EXTRA_GUI_OPTIONS_TERMINATOR
-};
-
uint32 XeenEngine::getGameID() const {
return _gameDescription->gameID;
}
@@ -95,15 +68,12 @@ bool XeenEngine::getIsCD() const {
}
} // End of namespace Xeen
+} // End of namespace MM
-class XeenMetaEngine : public AdvancedMetaEngine {
+class MMMetaEngine : public AdvancedMetaEngine {
public:
const char *getName() const override {
- return "xeen";
- }
-
- const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
- return Xeen::optionsList;
+ return "mm";
}
bool hasFeature(MetaEngineFeature f) const override;
@@ -114,7 +84,7 @@ public:
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
};
-bool XeenMetaEngine::hasFeature(MetaEngineFeature f) const {
+bool MMMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
@@ -126,24 +96,24 @@ bool XeenMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSimpleSavesNames);
}
-bool Xeen::XeenEngine::hasFeature(EngineFeature f) const {
+bool MM::Xeen::XeenEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
-Common::Error XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- const Xeen::XeenGameDescription *gd = (const Xeen::XeenGameDescription *)desc;
+Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const MM::MightAndMagicGameDescription *gd = (const MM::MightAndMagicGameDescription *)desc;
switch (gd->gameID) {
- case Xeen::GType_Clouds:
- case Xeen::GType_DarkSide:
- case Xeen::GType_WorldOfXeen:
- *engine = new Xeen::WorldOfXeen::WorldOfXeenEngine(syst, gd);
+ case MM::GType_Clouds:
+ case MM::GType_DarkSide:
+ case MM::GType_WorldOfXeen:
+ *engine = new MM::Xeen::WorldOfXeen::WorldOfXeenEngine(syst, gd);
break;
- case Xeen::GType_Swords:
- *engine = new Xeen::SwordsOfXeen::SwordsOfXeenEngine(syst, gd);
+ case MM::GType_Swords:
+ *engine = new MM::Xeen::SwordsOfXeen::SwordsOfXeenEngine(syst, gd);
break;
default:
return Common::kUnsupportedGameidError;
@@ -152,12 +122,12 @@ Common::Error XeenMetaEngine::createInstance(OSystem *syst, Engine **engine, con
return Common::kNoError;
}
-SaveStateList XeenMetaEngine::listSaves(const char *target) const {
+SaveStateList MMMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
Common::String saveDesc;
Common::String pattern = Common::String::format("%s.###", target);
- Xeen::XeenSavegameHeader header;
+ MM::Xeen::XeenSavegameHeader header;
filenames = saveFileMan->listSavefiles(pattern);
@@ -170,7 +140,7 @@ SaveStateList XeenMetaEngine::listSaves(const char *target) const {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- if (Xeen::SavesManager::readSavegameHeader(in, header))
+ if (MM::Xeen::SavesManager::readSavegameHeader(in, header))
saveList.push_back(SaveStateDescriptor(this, slot, header._saveName));
delete in;
@@ -182,22 +152,22 @@ SaveStateList XeenMetaEngine::listSaves(const char *target) const {
return saveList;
}
-int XeenMetaEngine::getMaximumSaveSlot() const {
+int MMMetaEngine::getMaximumSaveSlot() const {
return MAX_SAVES;
}
-void XeenMetaEngine::removeSaveState(const char *target, int slot) const {
+void MMMetaEngine::removeSaveState(const char *target, int slot) const {
Common::String filename = Common::String::format("%s.%03d", target, slot);
g_system->getSavefileManager()->removeSavefile(filename);
}
-SaveStateDescriptor XeenMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+SaveStateDescriptor MMMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::String filename = Common::String::format("%s.%03d", target, slot);
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
if (f) {
- Xeen::XeenSavegameHeader header;
- if (!Xeen::SavesManager::readSavegameHeader(f, header, false)) {
+ MM::Xeen::XeenSavegameHeader header;
+ if (!MM::Xeen::SavesManager::readSavegameHeader(f, header, false)) {
delete f;
return SaveStateDescriptor();
}
@@ -217,8 +187,8 @@ SaveStateDescriptor XeenMetaEngine::querySaveMetaInfos(const char *target, int s
return SaveStateDescriptor();
}
-#if PLUGIN_ENABLED_DYNAMIC(XEEN)
- REGISTER_PLUGIN_DYNAMIC(XEEN, PLUGIN_TYPE_ENGINE, XeenMetaEngine);
+#if PLUGIN_ENABLED_DYNAMIC(MM)
+ REGISTER_PLUGIN_DYNAMIC(MM, PLUGIN_TYPE_ENGINE, MMMetaEngine);
#else
- REGISTER_PLUGIN_STATIC(XEEN, PLUGIN_TYPE_ENGINE, XeenMetaEngine);
+ REGISTER_PLUGIN_STATIC(MM, PLUGIN_TYPE_ENGINE, MMMetaEngine);
#endif
diff --git a/engines/mm/mm.h b/engines/mm/mm.h
new file mode 100644
index 00000000000..e288edaf212
--- /dev/null
+++ b/engines/mm/mm.h
@@ -0,0 +1,36 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_MM_H
+#define MM_MM_H
+
+namespace MM {
+
+enum MightAndMagicDebugChannels {
+ kDebugPath = 1 << 0,
+ kDebugScripts = 1 << 1,
+ kDebugGraphics = 1 << 2,
+ kDebugSound = 1 << 3
+};
+
+} // namespace MM
+
+#endif // MM_MM_H
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
new file mode 100644
index 00000000000..e03b9fb3454
--- /dev/null
+++ b/engines/mm/module.mk
@@ -0,0 +1,73 @@
+MODULE := engines/mm
+
+MODULE_OBJS := \
+ metaengine.o \
+ xeen/worldofxeen/clouds_cutscenes.o \
+ xeen/worldofxeen/darkside_cutscenes.o \
+ xeen/worldofxeen/worldofxeen_cutscenes.o \
+ xeen/worldofxeen/worldofxeen_menu.o \
+ xeen/worldofxeen/worldofxeen.o \
+ xeen/swordsofxeen/swordsofxeen.o \
+ xeen/swordsofxeen/swordsofxeen_menu.o \
+ xeen/dialogs/credits_screen.o \
+ xeen/dialogs/dialogs.o \
+ xeen/dialogs/dialogs_awards.o \
+ xeen/dialogs/dialogs_char_info.o \
+ xeen/dialogs/dialogs_control_panel.o \
+ xeen/dialogs/dialogs_copy_protection.o \
+ xeen/dialogs/dialogs_create_char.o \
+ xeen/dialogs/dialogs_difficulty.o \
+ xeen/dialogs/dialogs_dismiss.o \
+ xeen/dialogs/dialogs_exchange.o \
+ xeen/dialogs/dialogs_info.o \
+ xeen/dialogs/dialogs_input.o \
+ xeen/dialogs/dialogs_items.o \
+ xeen/dialogs/dialogs_map.o \
+ xeen/dialogs/dialogs_message.o \
+ xeen/dialogs/dialogs_party.o \
+ xeen/dialogs/dialogs_query.o \
+ xeen/dialogs/dialogs_quests.o \
+ xeen/dialogs/dialogs_quick_fight.o \
+ xeen/dialogs/dialogs_quick_ref.o \
+ xeen/dialogs/dialogs_spells.o \
+ xeen/dialogs/dialogs_whowill.o \
+ xeen/dialogs/please_wait.o \
+ xeen/character.o \
+ xeen/combat.o \
+ xeen/cutscenes.o \
+ xeen/debugger.o \
+ xeen/events.o \
+ xeen/files.o \
+ xeen/font.o \
+ xeen/interface.o \
+ xeen/interface_minimap.o \
+ xeen/interface_scene.o \
+ xeen/item.o \
+ xeen/locations.o \
+ xeen/map.o \
+ xeen/party.o \
+ xeen/patcher.o \
+ xeen/resources.o \
+ xeen/saves.o \
+ xeen/screen.o \
+ xeen/scripts.o \
+ xeen/sound.o \
+ xeen/sound_driver.o \
+ xeen/sound_driver_adlib.o \
+ xeen/spells.o \
+ xeen/sprites.o \
+ xeen/subtitles.o \
+ xeen/window.o \
+ xeen/xeen.o \
+ xeen/xsurface.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_MM), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
+
+# Detection objects
+DETECT_OBJS += $(MODULE)/detection.o
diff --git a/engines/xeen/character.cpp b/engines/mm/xeen/character.cpp
similarity index 99%
rename from engines/xeen/character.cpp
rename to engines/mm/xeen/character.cpp
index e5a08ffbda1..0b0476b3fb2 100644
--- a/engines/xeen/character.cpp
+++ b/engines/mm/xeen/character.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/character.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/character.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
AttributePair::AttributePair() {
@@ -1312,3 +1313,4 @@ void Character::clearConditions() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/character.h b/engines/mm/xeen/character.h
similarity index 95%
rename from engines/xeen/character.h
rename to engines/mm/xeen/character.h
index f785f7c1333..5a7a8af2be8 100644
--- a/engines/xeen/character.h
+++ b/engines/mm/xeen/character.h
@@ -26,10 +26,11 @@
#include "common/array.h"
#include "common/rect.h"
#include "common/serializer.h"
-#include "xeen/combat.h"
-#include "xeen/item.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/combat.h"
+#include "mm/xeen/item.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
#define INV_ITEMS_TOTAL 9
@@ -43,9 +44,13 @@ enum Award {
LAKESIDE_GUILD_MEMBER = 85, NECROPOLIS_GUILD_MEMBER = 86, OLYMPUS_GUILD_MEMBER = 87
};
-enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 };
+enum Sex {
+ MALE = 0, FEMALE = 1, YES_PLEASE = 2
+};
-enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
+enum Race {
+ HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4
+};
enum CharacterClass {
CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3,
@@ -169,12 +174,16 @@ public:
/**
* Equality operator
*/
- bool operator==(const Character &src) const { return src._rosterId == _rosterId; }
+ bool operator==(const Character &src) const {
+ return src._rosterId == _rosterId;
+ }
/**
* Inequality operator
*/
- bool operator!=(const Character &src) const { return src._rosterId != _rosterId; }
+ bool operator!=(const Character &src) const {
+ return src._rosterId != _rosterId;
+ }
/**
* Clears the data for a character
@@ -371,5 +380,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_CHARACTER_H */
+#endif
diff --git a/engines/xeen/combat.cpp b/engines/mm/xeen/combat.cpp
similarity index 99%
rename from engines/xeen/combat.cpp
rename to engines/mm/xeen/combat.cpp
index 4dab1dd1325..63ecc183683 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/mm/xeen/combat.cpp
@@ -21,11 +21,12 @@
#include "common/algorithm.h"
#include "common/rect.h"
-#include "xeen/character.h"
-#include "xeen/combat.h"
-#include "xeen/interface.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/character.h"
+#include "mm/xeen/combat.h"
+#include "mm/xeen/interface.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
#define GRID_SIZE (7 * 7)
@@ -2129,3 +2130,4 @@ void Combat::reset() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/combat.h b/engines/mm/xeen/combat.h
similarity index 98%
rename from engines/xeen/combat.h
rename to engines/mm/xeen/combat.h
index 1772e18f211..f4db0b5a492 100644
--- a/engines/xeen/combat.h
+++ b/engines/mm/xeen/combat.h
@@ -24,9 +24,10 @@
#include "common/scummsys.h"
#include "common/rect.h"
-#include "xeen/files.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
#define MAX_NUM_MONSTERS 107
@@ -330,5 +331,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_COMBAT_H */
+#endif
diff --git a/engines/xeen/cutscenes.cpp b/engines/mm/xeen/cutscenes.cpp
similarity index 92%
rename from engines/xeen/cutscenes.cpp
rename to engines/mm/xeen/cutscenes.cpp
index 4682ba2750c..b2637251fac 100644
--- a/engines/xeen/cutscenes.cpp
+++ b/engines/mm/xeen/cutscenes.cpp
@@ -19,9 +19,10 @@
*
*/
-#include "xeen/cutscenes.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/cutscenes.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
uint Cutscenes::getSpeakingFrame(uint minFrame, uint maxFrame) {
@@ -34,3 +35,4 @@ bool Cutscenes::doScroll(bool rollUp, bool fadeIn) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/cutscenes.h b/engines/mm/xeen/cutscenes.h
similarity index 91%
rename from engines/xeen/cutscenes.h
rename to engines/mm/xeen/cutscenes.h
index b6bced2014c..72bdebebaab 100644
--- a/engines/xeen/cutscenes.h
+++ b/engines/mm/xeen/cutscenes.h
@@ -22,10 +22,11 @@
#ifndef XEEN_CUTSCENES_H
#define XEEN_CUTSCENES_H
-#include "xeen/files.h"
-#include "xeen/sprites.h"
-#include "xeen/subtitles.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/sprites.h"
+#include "mm/xeen/subtitles.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -52,5 +53,6 @@ protected:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_CUTSCENES_H */
+#endif
diff --git a/engines/xeen/debugger.cpp b/engines/mm/xeen/debugger.cpp
similarity index 98%
rename from engines/xeen/debugger.cpp
rename to engines/mm/xeen/debugger.cpp
index 00dd4872028..a6123f5ef10 100644
--- a/engines/xeen/debugger.cpp
+++ b/engines/mm/xeen/debugger.cpp
@@ -20,10 +20,11 @@
*/
#include "common/file.h"
-#include "xeen/xeen.h"
-#include "xeen/debugger.h"
-#include "xeen/files.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/debugger.h"
+#include "mm/xeen/files.h"
+namespace MM {
namespace Xeen {
static int strToInt(const char *s) {
@@ -273,3 +274,4 @@ bool Debugger::cmdLoadOriginal(int argc, const char **argv) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/debugger.h b/engines/mm/xeen/debugger.h
similarity index 98%
rename from engines/xeen/debugger.h
rename to engines/mm/xeen/debugger.h
index 7ae619f8778..6ae4d940006 100644
--- a/engines/xeen/debugger.h
+++ b/engines/mm/xeen/debugger.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "gui/debugger.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -103,5 +104,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DEBUGGER_H */
+#endif
diff --git a/engines/xeen/dialogs/credits_screen.cpp b/engines/mm/xeen/dialogs/credits_screen.cpp
similarity index 92%
rename from engines/xeen/dialogs/credits_screen.cpp
rename to engines/mm/xeen/dialogs/credits_screen.cpp
index fec0cfcd181..6acb382da5b 100644
--- a/engines/xeen/dialogs/credits_screen.cpp
+++ b/engines/mm/xeen/dialogs/credits_screen.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/credits_screen.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/credits_screen.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void CreditsScreen::show(XeenEngine *vm) {
@@ -69,3 +70,4 @@ void CreditsScreen::execute(const char *content) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/credits_screen.h b/engines/mm/xeen/dialogs/credits_screen.h
similarity index 93%
rename from engines/xeen/dialogs/credits_screen.h
rename to engines/mm/xeen/dialogs/credits_screen.h
index 0a9d19c7de2..d323a41720b 100644
--- a/engines/xeen/dialogs/credits_screen.h
+++ b/engines/mm/xeen/dialogs/credits_screen.h
@@ -22,8 +22,9 @@
#ifndef XEEN_DIALOGS_CREDITS_SCREEN_H
#define XEEN_DIALOGS_CREDITS_SCREEN_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class CreditsScreen: public ButtonContainer {
@@ -36,5 +37,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_CREDITS_SCREEN_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs.cpp b/engines/mm/xeen/dialogs/dialogs.cpp
similarity index 96%
rename from engines/xeen/dialogs/dialogs.cpp
rename to engines/mm/xeen/dialogs/dialogs.cpp
index 944cefc690d..9bb9a710667 100644
--- a/engines/xeen/dialogs/dialogs.cpp
+++ b/engines/mm/xeen/dialogs/dialogs.cpp
@@ -20,12 +20,13 @@
*/
#include "common/scummsys.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/events.h"
-#include "xeen/resources.h"
-#include "xeen/screen.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/screen.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void ButtonContainer::saveButtons() {
@@ -196,3 +197,4 @@ void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs.h b/engines/mm/xeen/dialogs/dialogs.h
similarity index 96%
rename from engines/xeen/dialogs/dialogs.h
rename to engines/mm/xeen/dialogs/dialogs.h
index 356eee7cda0..a6d047c757f 100644
--- a/engines/xeen/dialogs/dialogs.h
+++ b/engines/mm/xeen/dialogs/dialogs.h
@@ -25,10 +25,11 @@
#include "common/array.h"
#include "common/stack.h"
#include "common/rect.h"
-#include "xeen/cutscenes.h"
-#include "xeen/sprites.h"
-#include "xeen/xsurface.h"
+#include "mm/xeen/cutscenes.h"
+#include "mm/xeen/sprites.h"
+#include "mm/xeen/xsurface.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -147,5 +148,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_awards.cpp b/engines/mm/xeen/dialogs/dialogs_awards.cpp
similarity index 95%
rename from engines/xeen/dialogs/dialogs_awards.cpp
rename to engines/mm/xeen/dialogs/dialogs_awards.cpp
index 1533fb07560..375fa005c12 100644
--- a/engines/xeen/dialogs/dialogs_awards.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_awards.cpp
@@ -19,11 +19,12 @@
*
*/
-#include "xeen/dialogs/dialogs_awards.h"
-#include "xeen/party.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_awards.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void Awards::show(XeenEngine *vm, const Character *ch) {
@@ -128,3 +129,4 @@ void Awards::addButtons() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_awards.h b/engines/mm/xeen/dialogs/dialogs_awards.h
similarity index 92%
rename from engines/xeen/dialogs/dialogs_awards.h
rename to engines/mm/xeen/dialogs/dialogs_awards.h
index f1a94c66fe6..82e26b7deef 100644
--- a/engines/xeen/dialogs/dialogs_awards.h
+++ b/engines/mm/xeen/dialogs/dialogs_awards.h
@@ -22,9 +22,10 @@
#ifndef XEEN_DIALOGS_AWARDS_H
#define XEEN_DIALOGS_AWARDS_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/character.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/character.h"
+namespace MM {
namespace Xeen {
class Awards : public ButtonContainer {
@@ -47,5 +48,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_AWARDS_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_char_info.cpp b/engines/mm/xeen/dialogs/dialogs_char_info.cpp
similarity index 98%
rename from engines/xeen/dialogs/dialogs_char_info.cpp
rename to engines/mm/xeen/dialogs/dialogs_char_info.cpp
index 615a3609937..2ed1e867516 100644
--- a/engines/xeen/dialogs/dialogs_char_info.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_char_info.cpp
@@ -19,14 +19,15 @@
*
*/
-#include "xeen/dialogs/dialogs_awards.h"
-#include "xeen/dialogs/dialogs_char_info.h"
-#include "xeen/dialogs/dialogs_exchange.h"
-#include "xeen/dialogs/dialogs_items.h"
-#include "xeen/dialogs/dialogs_quick_ref.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-
+#include "mm/xeen/dialogs/dialogs_awards.h"
+#include "mm/xeen/dialogs/dialogs_char_info.h"
+#include "mm/xeen/dialogs/dialogs_exchange.h"
+#include "mm/xeen/dialogs/dialogs_items.h"
+#include "mm/xeen/dialogs/dialogs_quick_ref.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+
+namespace MM {
namespace Xeen {
void CharacterInfo::show(XeenEngine *vm, int charIndex) {
@@ -625,3 +626,4 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_char_info.h b/engines/mm/xeen/dialogs/dialogs_char_info.h
similarity index 93%
rename from engines/xeen/dialogs/dialogs_char_info.h
rename to engines/mm/xeen/dialogs/dialogs_char_info.h
index ab101e0d39f..53129ec4199 100644
--- a/engines/xeen/dialogs/dialogs_char_info.h
+++ b/engines/mm/xeen/dialogs/dialogs_char_info.h
@@ -22,10 +22,11 @@
#ifndef XEEN_DIALOGS_CHAR_INFO_H
#define XEEN_DIALOGS_CHAR_INFO_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/party.h"
-#include "xeen/window.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/window.h"
+namespace MM {
namespace Xeen {
class CharacterInfo : public ButtonContainer {
@@ -79,5 +80,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_CHAR_INFO_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_control_panel.cpp b/engines/mm/xeen/dialogs/dialogs_control_panel.cpp
similarity index 96%
rename from engines/xeen/dialogs/dialogs_control_panel.cpp
rename to engines/mm/xeen/dialogs/dialogs_control_panel.cpp
index f86cd793bb0..8ad487730cc 100644
--- a/engines/xeen/dialogs/dialogs_control_panel.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_control_panel.cpp
@@ -19,12 +19,13 @@
*
*/
-#include "xeen/dialogs/dialogs_control_panel.h"
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/party.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_control_panel.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
int ControlPanel::show(XeenEngine *vm) {
@@ -203,3 +204,4 @@ Common::String ControlPanel::getTimeText() const {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_control_panel.h b/engines/mm/xeen/dialogs/dialogs_control_panel.h
similarity index 95%
rename from engines/xeen/dialogs/dialogs_control_panel.h
rename to engines/mm/xeen/dialogs/dialogs_control_panel.h
index 55038d0ab8e..fc5ca126f1a 100644
--- a/engines/xeen/dialogs/dialogs_control_panel.h
+++ b/engines/mm/xeen/dialogs/dialogs_control_panel.h
@@ -22,8 +22,9 @@
#ifndef XEEN_DIALOGS_CONTROL_PANEL_H
#define XEEN_DIALOGS_CONTROL_PANEL_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class ControlPanel : public ButtonContainer {
@@ -61,5 +62,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_CONTROL_PANEL_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_copy_protection.cpp b/engines/mm/xeen/dialogs/dialogs_copy_protection.cpp
similarity index 92%
rename from engines/xeen/dialogs/dialogs_copy_protection.cpp
rename to engines/mm/xeen/dialogs/dialogs_copy_protection.cpp
index 0863ebeeb5e..ba850f645a3 100644
--- a/engines/xeen/dialogs/dialogs_copy_protection.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_copy_protection.cpp
@@ -19,11 +19,12 @@
*
*/
-#include "xeen/dialogs/dialogs_copy_protection.h"
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_copy_protection.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
bool CopyProtection::show(XeenEngine *vm) {
@@ -97,3 +98,4 @@ void CopyProtection::loadEntries() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_copy_protection.h b/engines/mm/xeen/dialogs/dialogs_copy_protection.h
similarity index 94%
rename from engines/xeen/dialogs/dialogs_copy_protection.h
rename to engines/mm/xeen/dialogs/dialogs_copy_protection.h
index f6596f3b8df..7c3d97ac6f7 100644
--- a/engines/xeen/dialogs/dialogs_copy_protection.h
+++ b/engines/mm/xeen/dialogs/dialogs_copy_protection.h
@@ -22,9 +22,10 @@
#ifndef XEEN_DIALOGS_COPY_PROTECTION_H
#define XEEN_DIALOGS_COPY_PROTECTION_H
-#include "xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
#include "common/array.h"
+namespace MM {
namespace Xeen {
class CopyProtection : public Input {
@@ -59,5 +60,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_COPY_PROTECTION_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_create_char.cpp b/engines/mm/xeen/dialogs/dialogs_create_char.cpp
similarity index 99%
rename from engines/xeen/dialogs/dialogs_create_char.cpp
rename to engines/mm/xeen/dialogs/dialogs_create_char.cpp
index a6de43440e8..7692b10f62a 100644
--- a/engines/xeen/dialogs/dialogs_create_char.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_create_char.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_create_char.h"
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_create_char.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void CreateCharacterDialog::show(XeenEngine *vm) {
@@ -640,3 +641,4 @@ bool CreateCharacterDialog::saveCharacter(Character &c, int classId, Race race,
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_create_char.h b/engines/mm/xeen/dialogs/dialogs_create_char.h
similarity index 96%
rename from engines/xeen/dialogs/dialogs_create_char.h
rename to engines/mm/xeen/dialogs/dialogs_create_char.h
index d15dd09ac5c..4b9d04d6b0a 100644
--- a/engines/xeen/dialogs/dialogs_create_char.h
+++ b/engines/mm/xeen/dialogs/dialogs_create_char.h
@@ -22,9 +22,10 @@
#ifndef XEEN_DIALOGS_CREATE_CHAR_H
#define XEEN_DIALOGS_CREATE_CHAR_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/character.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/character.h"
+namespace MM {
namespace Xeen {
class CreateCharacterDialog : public ButtonContainer {
@@ -119,5 +120,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_CREATE_CHAR_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_difficulty.cpp b/engines/mm/xeen/dialogs/dialogs_difficulty.cpp
similarity index 93%
rename from engines/xeen/dialogs/dialogs_difficulty.cpp
rename to engines/mm/xeen/dialogs/dialogs_difficulty.cpp
index 40c7bdba22b..b3f8a2758d5 100644
--- a/engines/xeen/dialogs/dialogs_difficulty.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_difficulty.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_difficulty.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_difficulty.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
int DifficultyDialog::show(XeenEngine *vm) {
@@ -73,3 +74,4 @@ void DifficultyDialog::loadButtons() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_difficulty.h b/engines/mm/xeen/dialogs/dialogs_difficulty.h
similarity index 92%
rename from engines/xeen/dialogs/dialogs_difficulty.h
rename to engines/mm/xeen/dialogs/dialogs_difficulty.h
index f1143397983..21318d1d5ba 100644
--- a/engines/xeen/dialogs/dialogs_difficulty.h
+++ b/engines/mm/xeen/dialogs/dialogs_difficulty.h
@@ -22,9 +22,10 @@
#ifndef XEEN_DIALOGS_DIFFICULTY_H
#define XEEN_DIALOGS_DIFFICULTY_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/party.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/party.h"
+namespace MM {
namespace Xeen {
class DifficultyDialog : public ButtonContainer {
@@ -55,5 +56,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_DIFFICULTY_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_dismiss.cpp b/engines/mm/xeen/dialogs/dialogs_dismiss.cpp
similarity index 94%
rename from engines/xeen/dialogs/dialogs_dismiss.cpp
rename to engines/mm/xeen/dialogs/dialogs_dismiss.cpp
index 13664bd3142..c83cd533a93 100644
--- a/engines/xeen/dialogs/dialogs_dismiss.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_dismiss.cpp
@@ -19,11 +19,12 @@
*
*/
-#include "xeen/dialogs/dialogs_dismiss.h"
-#include "xeen/party.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_dismiss.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void Dismiss::show(XeenEngine *vm) {
@@ -98,3 +99,4 @@ void Dismiss::loadButtons() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_dismiss.h b/engines/mm/xeen/dialogs/dialogs_dismiss.h
similarity index 91%
rename from engines/xeen/dialogs/dialogs_dismiss.h
rename to engines/mm/xeen/dialogs/dialogs_dismiss.h
index 75d5814bdbb..e06157dfb51 100644
--- a/engines/xeen/dialogs/dialogs_dismiss.h
+++ b/engines/mm/xeen/dialogs/dialogs_dismiss.h
@@ -22,9 +22,10 @@
#ifndef XEEN_DIALOGS_DISMISS_H
#define XEEN_DIALOGS_DISMISS_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/party.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/party.h"
+namespace MM {
namespace Xeen {
class Dismiss : public ButtonContainer {
@@ -41,5 +42,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_DISMISS_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_exchange.cpp b/engines/mm/xeen/dialogs/dialogs_exchange.cpp
similarity index 94%
rename from engines/xeen/dialogs/dialogs_exchange.cpp
rename to engines/mm/xeen/dialogs/dialogs_exchange.cpp
index d2d4ea000c5..e5d852b0d87 100644
--- a/engines/xeen/dialogs/dialogs_exchange.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_exchange.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_exchange.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_exchange.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void ExchangeDialog::show(XeenEngine *vm, Character *&c, int &charIndex) {
@@ -77,3 +78,4 @@ void ExchangeDialog::loadButtons() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_exchange.h b/engines/mm/xeen/dialogs/dialogs_exchange.h
similarity index 92%
rename from engines/xeen/dialogs/dialogs_exchange.h
rename to engines/mm/xeen/dialogs/dialogs_exchange.h
index 4412eb5056b..ad6e9998fb6 100644
--- a/engines/xeen/dialogs/dialogs_exchange.h
+++ b/engines/mm/xeen/dialogs/dialogs_exchange.h
@@ -22,9 +22,10 @@
#ifndef XEEN_DIALOGS_EXCHANGE_H
#define XEEN_DIALOGS_EXCHANGE_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/party.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/party.h"
+namespace MM {
namespace Xeen {
class ExchangeDialog : public ButtonContainer {
@@ -41,5 +42,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_EXCHANGE_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_info.cpp b/engines/mm/xeen/dialogs/dialogs_info.cpp
similarity index 96%
rename from engines/xeen/dialogs/dialogs_info.cpp
rename to engines/mm/xeen/dialogs/dialogs_info.cpp
index 16a447d00ef..1ea7d7e573d 100644
--- a/engines/xeen/dialogs/dialogs_info.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_info.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_info.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_info.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void InfoDialog::show(XeenEngine *vm) {
@@ -126,3 +127,4 @@ void InfoDialog::protectionText() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_info.h b/engines/mm/xeen/dialogs/dialogs_info.h
similarity index 93%
rename from engines/xeen/dialogs/dialogs_info.h
rename to engines/mm/xeen/dialogs/dialogs_info.h
index f27039f29be..f1e38ea68a3 100644
--- a/engines/xeen/dialogs/dialogs_info.h
+++ b/engines/mm/xeen/dialogs/dialogs_info.h
@@ -23,8 +23,9 @@
#define XEEN_DIALOGS_INFO_H
#include "common/str-array.h"
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class InfoDialog : public ButtonContainer {
@@ -41,5 +42,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_INFO_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_input.cpp b/engines/mm/xeen/dialogs/dialogs_input.cpp
similarity index 98%
rename from engines/xeen/dialogs/dialogs_input.cpp
rename to engines/mm/xeen/dialogs/dialogs_input.cpp
index 55f9cd431fe..fbdd4f62767 100644
--- a/engines/xeen/dialogs/dialogs_input.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_input.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/scripts.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/scripts.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
int Input::show(XeenEngine *vm, Window *window, Common::String &line,
@@ -402,3 +403,4 @@ int HowMuch::execute() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_input.h b/engines/mm/xeen/dialogs/dialogs_input.h
similarity index 96%
rename from engines/xeen/dialogs/dialogs_input.h
rename to engines/mm/xeen/dialogs/dialogs_input.h
index 1c7a85fef1c..4ec8fd8b2cc 100644
--- a/engines/xeen/dialogs/dialogs_input.h
+++ b/engines/mm/xeen/dialogs/dialogs_input.h
@@ -23,9 +23,10 @@
#define XEEN_DIALOGS_STRING_INPUT_H
#include "common/keyboard.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/screen.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/screen.h"
+namespace MM {
namespace Xeen {
class Input : public ButtonContainer {
@@ -103,5 +104,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_STRING_INPUT_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_items.cpp b/engines/mm/xeen/dialogs/dialogs_items.cpp
similarity index 99%
rename from engines/xeen/dialogs/dialogs_items.cpp
rename to engines/mm/xeen/dialogs/dialogs_items.cpp
index 021c984453c..389ca5827f2 100644
--- a/engines/xeen/dialogs/dialogs_items.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_items.cpp
@@ -19,12 +19,13 @@
*
*/
-#include "xeen/dialogs/dialogs_items.h"
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/dialogs/dialogs_quests.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_items.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/dialogs/dialogs_quests.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
Character *ItemsDialog::show(XeenEngine *vm, Character *c, ItemsMode mode) {
@@ -1037,3 +1038,4 @@ int ItemSelectionDialog::execute() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_items.h b/engines/mm/xeen/dialogs/dialogs_items.h
similarity index 95%
rename from engines/xeen/dialogs/dialogs_items.h
rename to engines/mm/xeen/dialogs/dialogs_items.h
index 9912697eafb..7c3f0361b63 100644
--- a/engines/xeen/dialogs/dialogs_items.h
+++ b/engines/mm/xeen/dialogs/dialogs_items.h
@@ -22,10 +22,11 @@
#ifndef XEEN_DIALOGS_ITEMS_H
#define XEEN_DIALOGS_ITEMS_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/party.h"
-#include "xeen/window.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/window.h"
+namespace MM {
namespace Xeen {
enum ItemsMode {
@@ -109,5 +110,6 @@ public:
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_ITEMS_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_map.cpp b/engines/mm/xeen/dialogs/dialogs_map.cpp
similarity index 98%
rename from engines/xeen/dialogs/dialogs_map.cpp
rename to engines/mm/xeen/dialogs/dialogs_map.cpp
index 17700a00d70..7c65c239d09 100644
--- a/engines/xeen/dialogs/dialogs_map.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_map.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_map.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_map.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
#define MAP_SIZE 16
@@ -458,3 +459,4 @@ void MapDialog::drawIndoors() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_map.h b/engines/mm/xeen/dialogs/dialogs_map.h
similarity index 94%
rename from engines/xeen/dialogs/dialogs_map.h
rename to engines/mm/xeen/dialogs/dialogs_map.h
index a9238936385..7ef07ca5bfe 100644
--- a/engines/xeen/dialogs/dialogs_map.h
+++ b/engines/mm/xeen/dialogs/dialogs_map.h
@@ -22,8 +22,9 @@
#ifndef XEEN_DIALOGS_MAP_H
#define XEEN_DIALOGS_MAP_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -57,5 +58,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_AUTOMAP_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_message.cpp b/engines/mm/xeen/dialogs/dialogs_message.cpp
similarity index 95%
rename from engines/xeen/dialogs/dialogs_message.cpp
rename to engines/mm/xeen/dialogs/dialogs_message.cpp
index 7c7db468273..1b17142bdd4 100644
--- a/engines/xeen/dialogs/dialogs_message.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_message.cpp
@@ -20,10 +20,11 @@
*/
#include "common/scummsys.h"
-#include "xeen/dialogs/dialogs_message.h"
-#include "xeen/events.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_message.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void MessageDialog::show(XeenEngine *vm, const Common::String &msg, MessageWaitType waitType) {
@@ -120,3 +121,4 @@ void CantCast::execute(int spellId, int componentNum) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_message.h b/engines/mm/xeen/dialogs/dialogs_message.h
similarity index 93%
rename from engines/xeen/dialogs/dialogs_message.h
rename to engines/mm/xeen/dialogs/dialogs_message.h
index 6a4c432568a..54ad28fc47b 100644
--- a/engines/xeen/dialogs/dialogs_message.h
+++ b/engines/mm/xeen/dialogs/dialogs_message.h
@@ -22,9 +22,10 @@
#ifndef XEEN_dialogs_message_H
#define XEEN_dialogs_message_H
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/character.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/character.h"
+namespace MM {
namespace Xeen {
enum MessageWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1,
@@ -56,5 +57,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_dialogs_message_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_party.cpp b/engines/mm/xeen/dialogs/dialogs_party.cpp
similarity index 97%
rename from engines/xeen/dialogs/dialogs_party.cpp
rename to engines/mm/xeen/dialogs/dialogs_party.cpp
index c814ff60703..f1717cf75fd 100644
--- a/engines/xeen/dialogs/dialogs_party.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_party.cpp
@@ -19,16 +19,17 @@
*
*/
-#include "xeen/dialogs/dialogs_char_info.h"
-#include "xeen/dialogs/dialogs_create_char.h"
-#include "xeen/dialogs/dialogs_party.h"
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/character.h"
-#include "xeen/events.h"
-#include "xeen/party.h"
-#include "xeen/xeen.h"
-
+#include "mm/xeen/dialogs/dialogs_char_info.h"
+#include "mm/xeen/dialogs/dialogs_create_char.h"
+#include "mm/xeen/dialogs/dialogs_party.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/character.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/xeen.h"
+
+namespace MM {
namespace Xeen {
PartyDialog::PartyDialog(XeenEngine *vm) : ButtonContainer(vm),
@@ -444,3 +445,4 @@ int PartyDialog::selectCharacter(bool isDelete, int firstDisplayChar) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_party.h b/engines/mm/xeen/dialogs/dialogs_party.h
similarity index 92%
rename from engines/xeen/dialogs/dialogs_party.h
rename to engines/mm/xeen/dialogs/dialogs_party.h
index ba2f8003145..5eed32c03ac 100644
--- a/engines/xeen/dialogs/dialogs_party.h
+++ b/engines/mm/xeen/dialogs/dialogs_party.h
@@ -23,11 +23,12 @@
#define XEEN_DIALOGS_PARTY_H
#include "common/array.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/interface.h"
-#include "xeen/screen.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/interface.h"
+#include "mm/xeen/screen.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
/**
@@ -87,5 +88,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_PARTY_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_query.cpp b/engines/mm/xeen/dialogs/dialogs_query.cpp
similarity index 97%
rename from engines/xeen/dialogs/dialogs_query.cpp
rename to engines/mm/xeen/dialogs/dialogs_query.cpp
index f1058f18a94..5b5a8cd34fe 100644
--- a/engines/xeen/dialogs/dialogs_query.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_query.cpp
@@ -19,9 +19,10 @@
*
*/
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
bool Confirm::show(XeenEngine *vm, const Common::String &msg, int mode) {
@@ -162,3 +163,4 @@ bool YesNo::execute(bool type, bool townFlag) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_query.h b/engines/mm/xeen/dialogs/dialogs_query.h
similarity index 94%
rename from engines/xeen/dialogs/dialogs_query.h
rename to engines/mm/xeen/dialogs/dialogs_query.h
index bcf3325b7db..2b53025abc0 100644
--- a/engines/xeen/dialogs/dialogs_query.h
+++ b/engines/mm/xeen/dialogs/dialogs_query.h
@@ -22,8 +22,9 @@
#ifndef XEEN_DIALOGS_QUERY_H
#define XEEN_DIALOGS_QUERY_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class Confirm : public ButtonContainer {
@@ -45,5 +46,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_QUERY_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_quests.cpp b/engines/mm/xeen/dialogs/dialogs_quests.cpp
similarity index 97%
rename from engines/xeen/dialogs/dialogs_quests.cpp
rename to engines/mm/xeen/dialogs/dialogs_quests.cpp
index 2457dec4d5e..f127c7dae96 100644
--- a/engines/xeen/dialogs/dialogs_quests.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_quests.cpp
@@ -20,11 +20,12 @@
*/
#include "common/scummsys.h"
-#include "xeen/dialogs/dialogs_quests.h"
-#include "xeen/events.h"
-#include "xeen/party.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_quests.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
#define MAX_DIALOG_LINES 128
@@ -276,3 +277,4 @@ void Quests::loadQuestNotes() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_quests.h b/engines/mm/xeen/dialogs/dialogs_quests.h
similarity index 93%
rename from engines/xeen/dialogs/dialogs_quests.h
rename to engines/mm/xeen/dialogs/dialogs_quests.h
index a3fb0362ea5..47d0ec6c6b7 100644
--- a/engines/xeen/dialogs/dialogs_quests.h
+++ b/engines/mm/xeen/dialogs/dialogs_quests.h
@@ -23,8 +23,9 @@
#define XEEN_DIALOGS_QUESTS_H
#include "common/str-array.h"
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class Quests : public ButtonContainer {
@@ -44,5 +45,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_QUESTS_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_quick_fight.cpp b/engines/mm/xeen/dialogs/dialogs_quick_fight.cpp
similarity index 95%
rename from engines/xeen/dialogs/dialogs_quick_fight.cpp
rename to engines/mm/xeen/dialogs/dialogs_quick_fight.cpp
index 33933c7b342..12c299ed7d4 100644
--- a/engines/xeen/dialogs/dialogs_quick_fight.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_quick_fight.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_quick_fight.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_quick_fight.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void QuickFight::show(XeenEngine *vm, Character *currentChar) {
@@ -95,3 +96,4 @@ void QuickFight::loadButtons() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_quick_fight.h b/engines/mm/xeen/dialogs/dialogs_quick_fight.h
similarity index 90%
rename from engines/xeen/dialogs/dialogs_quick_fight.h
rename to engines/mm/xeen/dialogs/dialogs_quick_fight.h
index bfd3d126939..6cc2ae855ae 100644
--- a/engines/xeen/dialogs/dialogs_quick_fight.h
+++ b/engines/mm/xeen/dialogs/dialogs_quick_fight.h
@@ -22,10 +22,11 @@
#ifndef XEEN_DIALOGS_QUICK_FIGHT_H
#define XEEN_DIALOGS_QUICK_FIGHT_H
-#include "xeen/character.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/character.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
class QuickFight : public ButtonContainer {
@@ -55,5 +56,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_QUICK_FIGHT_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_quick_ref.cpp b/engines/mm/xeen/dialogs/dialogs_quick_ref.cpp
similarity index 96%
rename from engines/xeen/dialogs/dialogs_quick_ref.cpp
rename to engines/mm/xeen/dialogs/dialogs_quick_ref.cpp
index 91ecd877877..70ce7e2dc41 100644
--- a/engines/xeen/dialogs/dialogs_quick_ref.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_quick_ref.cpp
@@ -20,10 +20,11 @@
*/
#include "common/config-manager.h"
-#include "xeen/dialogs/dialogs_quick_ref.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_quick_ref.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
void QuickReferenceDialog::show(XeenEngine *vm) {
@@ -107,3 +108,4 @@ void QuickReferenceDialog::execute() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_quick_ref.h b/engines/mm/xeen/dialogs/dialogs_quick_ref.h
similarity index 93%
rename from engines/xeen/dialogs/dialogs_quick_ref.h
rename to engines/mm/xeen/dialogs/dialogs_quick_ref.h
index f79bf366e76..cb3e3adbeb4 100644
--- a/engines/xeen/dialogs/dialogs_quick_ref.h
+++ b/engines/mm/xeen/dialogs/dialogs_quick_ref.h
@@ -22,8 +22,9 @@
#ifndef XEEN_DIALOGS_QUICK_REF_H
#define XEEN_DIALOGS_QUICK_REF_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class QuickReferenceDialog : public ButtonContainer {
@@ -41,5 +42,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_QUICK_REF_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_spells.cpp b/engines/mm/xeen/dialogs/dialogs_spells.cpp
similarity index 99%
rename from engines/xeen/dialogs/dialogs_spells.cpp
rename to engines/mm/xeen/dialogs/dialogs_spells.cpp
index ef4bb803d47..4e0e9efb244 100644
--- a/engines/xeen/dialogs/dialogs_spells.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_spells.cpp
@@ -19,14 +19,15 @@
*
*/
-#include "xeen/dialogs/dialogs_spells.h"
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/resources.h"
-#include "xeen/spells.h"
-#include "xeen/sprites.h"
-#include "xeen/xeen.h"
-
+#include "mm/xeen/dialogs/dialogs_spells.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/spells.h"
+#include "mm/xeen/sprites.h"
+#include "mm/xeen/xeen.h"
+
+namespace MM {
namespace Xeen {
Character *SpellsDialog::show(XeenEngine *vm, ButtonContainer *priorDialog,
@@ -1062,3 +1063,4 @@ void DetectMonsters::execute() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_spells.h b/engines/mm/xeen/dialogs/dialogs_spells.h
similarity index 97%
rename from engines/xeen/dialogs/dialogs_spells.h
rename to engines/mm/xeen/dialogs/dialogs_spells.h
index 245966ad07e..fdb497afc7d 100644
--- a/engines/xeen/dialogs/dialogs_spells.h
+++ b/engines/mm/xeen/dialogs/dialogs_spells.h
@@ -23,9 +23,10 @@
#define XEEN_DIALOGS_SPELLS_H
#include "common/array.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/party.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/party.h"
+namespace MM {
namespace Xeen {
enum SpellDialogMode {
@@ -177,5 +178,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_SPELLS_H */
+#endif
diff --git a/engines/xeen/dialogs/dialogs_whowill.cpp b/engines/mm/xeen/dialogs/dialogs_whowill.cpp
similarity index 95%
rename from engines/xeen/dialogs/dialogs_whowill.cpp
rename to engines/mm/xeen/dialogs/dialogs_whowill.cpp
index 501dd8f08e3..5549c6297d0 100644
--- a/engines/xeen/dialogs/dialogs_whowill.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_whowill.cpp
@@ -19,10 +19,11 @@
*
*/
-#include "xeen/dialogs/dialogs_whowill.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_whowill.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
int WhoWill::show(XeenEngine *vm, int message, int action, bool type) {
@@ -102,3 +103,4 @@ int WhoWill::execute(int message, int action, bool type) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/dialogs_whowill.h b/engines/mm/xeen/dialogs/dialogs_whowill.h
similarity index 93%
rename from engines/xeen/dialogs/dialogs_whowill.h
rename to engines/mm/xeen/dialogs/dialogs_whowill.h
index 584243d4c14..39d742b228b 100644
--- a/engines/xeen/dialogs/dialogs_whowill.h
+++ b/engines/mm/xeen/dialogs/dialogs_whowill.h
@@ -22,8 +22,9 @@
#ifndef XEEN_DIALOGS_WHOWHILL_H
#define XEEN_DIALOGS_WHOWHILL_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class WhoWill : public ButtonContainer {
@@ -36,5 +37,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_WHOWHILL_H */
+#endif
diff --git a/engines/xeen/dialogs/please_wait.cpp b/engines/mm/xeen/dialogs/please_wait.cpp
similarity index 88%
rename from engines/xeen/dialogs/please_wait.cpp
rename to engines/mm/xeen/dialogs/please_wait.cpp
index 686b2016ce5..1ebc0c1d061 100644
--- a/engines/xeen/dialogs/please_wait.cpp
+++ b/engines/mm/xeen/dialogs/please_wait.cpp
@@ -19,11 +19,12 @@
*
*/
-#include "xeen/dialogs/please_wait.h"
-#include "xeen/resources.h"
-#include "xeen/window.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/dialogs/please_wait.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/window.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
PleaseWait::PleaseWait(bool isOops) {
@@ -48,3 +49,4 @@ void PleaseWait::show() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/dialogs/please_wait.h b/engines/mm/xeen/dialogs/please_wait.h
similarity index 93%
rename from engines/xeen/dialogs/please_wait.h
rename to engines/mm/xeen/dialogs/please_wait.h
index 6caf4bf998c..af942752057 100644
--- a/engines/xeen/dialogs/please_wait.h
+++ b/engines/mm/xeen/dialogs/please_wait.h
@@ -22,8 +22,9 @@
#ifndef XEEN_DIALOGS_PLEASE_WAIT_H
#define XEEN_DIALOGS_PLEASE_WAIT_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
class PleaseWait {
@@ -40,5 +41,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_DIALOGS_PLEASE_WAIT_H */
+#endif
diff --git a/engines/xeen/events.cpp b/engines/mm/xeen/events.cpp
similarity index 97%
rename from engines/xeen/events.cpp
rename to engines/mm/xeen/events.cpp
index db5cec0e646..ad130361694 100644
--- a/engines/xeen/events.cpp
+++ b/engines/mm/xeen/events.cpp
@@ -24,10 +24,11 @@
#include "common/events.h"
#include "common/endian.h"
#include "engines/util.h"
-#include "xeen/xeen.h"
-#include "xeen/events.h"
-#include "xeen/screen.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/screen.h"
+namespace MM {
namespace Xeen {
EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _playTime(0), _gameCounter(0),
@@ -217,3 +218,4 @@ bool EventsManager::isModifierKey(const Common::KeyCode &keycode) const {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/events.h b/engines/mm/xeen/events.h
similarity index 98%
rename from engines/xeen/events.h
rename to engines/mm/xeen/events.h
index 372a9d9c05a..d0a7a1567bf 100644
--- a/engines/xeen/events.h
+++ b/engines/mm/xeen/events.h
@@ -25,8 +25,9 @@
#include "common/scummsys.h"
#include "common/events.h"
#include "common/queue.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
#define GAME_FRAME_RATE (1000 / 50)
@@ -196,5 +197,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_EVENTS_H */
+#endif
diff --git a/engines/xeen/files.cpp b/engines/mm/xeen/files.cpp
similarity index 99%
rename from engines/xeen/files.cpp
rename to engines/mm/xeen/files.cpp
index a3eb2d8e713..563979dae11 100644
--- a/engines/xeen/files.cpp
+++ b/engines/mm/xeen/files.cpp
@@ -24,10 +24,11 @@
#include "common/memstream.h"
#include "common/substream.h"
#include "common/textconsole.h"
-#include "xeen/xeen.h"
-#include "xeen/files.h"
-#include "xeen/saves.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/saves.h"
+namespace MM {
namespace Xeen {
uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) {
@@ -652,3 +653,4 @@ void OutFile::finalize() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/files.h b/engines/mm/xeen/files.h
similarity index 99%
rename from engines/xeen/files.h
rename to engines/mm/xeen/files.h
index 51807b88996..2bafc97663a 100644
--- a/engines/xeen/files.h
+++ b/engines/mm/xeen/files.h
@@ -31,6 +31,7 @@
#include "common/str-array.h"
#include "graphics/surface.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -396,5 +397,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_FILES_H */
+#endif
diff --git a/engines/xeen/font.cpp b/engines/mm/xeen/font.cpp
similarity index 98%
rename from engines/xeen/font.cpp
rename to engines/mm/xeen/font.cpp
index 04e886d1179..0cba4f54bb3 100644
--- a/engines/xeen/font.cpp
+++ b/engines/mm/xeen/font.cpp
@@ -20,10 +20,11 @@
*/
#include "common/endian.h"
-#include "xeen/font.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/font.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
const byte *FontData::_fontData;
@@ -422,3 +423,4 @@ void FontSurface::writeChar(char c, const Common::Rect &clipRect) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/font.h b/engines/mm/xeen/font.h
similarity index 97%
rename from engines/xeen/font.h
rename to engines/mm/xeen/font.h
index 722d51566c5..58cfd46dc1f 100644
--- a/engines/xeen/font.h
+++ b/engines/mm/xeen/font.h
@@ -23,8 +23,9 @@
#define XEEN_FONT_H
#include "common/language.h"
-#include "xeen/xsurface.h"
+#include "mm/xeen/xsurface.h"
+namespace MM {
namespace Xeen {
#define FONT_WIDTH 8
@@ -121,5 +122,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_FONT_H */
+#endif
diff --git a/engines/xeen/interface.cpp b/engines/mm/xeen/interface.cpp
similarity index 98%
rename from engines/xeen/interface.cpp
rename to engines/mm/xeen/interface.cpp
index 37e80d508ec..ca9827128a0 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/mm/xeen/interface.cpp
@@ -19,24 +19,25 @@
*
*/
-#include "xeen/interface.h"
-#include "xeen/dialogs/dialogs_char_info.h"
-#include "xeen/dialogs/dialogs_control_panel.h"
-#include "xeen/dialogs/dialogs_dismiss.h"
-#include "xeen/dialogs/dialogs_message.h"
-#include "xeen/dialogs/dialogs_quick_fight.h"
-#include "xeen/dialogs/dialogs_info.h"
-#include "xeen/dialogs/dialogs_items.h"
-#include "xeen/dialogs/dialogs_map.h"
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/dialogs/dialogs_quests.h"
-#include "xeen/dialogs/dialogs_quick_ref.h"
-#include "xeen/dialogs/dialogs_spells.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-
-#include "xeen/dialogs/dialogs_party.h"
-
+#include "mm/xeen/interface.h"
+#include "mm/xeen/dialogs/dialogs_char_info.h"
+#include "mm/xeen/dialogs/dialogs_control_panel.h"
+#include "mm/xeen/dialogs/dialogs_dismiss.h"
+#include "mm/xeen/dialogs/dialogs_message.h"
+#include "mm/xeen/dialogs/dialogs_quick_fight.h"
+#include "mm/xeen/dialogs/dialogs_info.h"
+#include "mm/xeen/dialogs/dialogs_items.h"
+#include "mm/xeen/dialogs/dialogs_map.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/dialogs/dialogs_quests.h"
+#include "mm/xeen/dialogs/dialogs_quick_ref.h"
+#include "mm/xeen/dialogs/dialogs_spells.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+
+#include "mm/xeen/dialogs/dialogs_party.h"
+
+namespace MM {
namespace Xeen {
enum {
@@ -1932,3 +1933,4 @@ void Interface::obscureScene(Obscurity obscurity) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/interface.h b/engines/mm/xeen/interface.h
similarity index 95%
rename from engines/xeen/interface.h
rename to engines/mm/xeen/interface.h
index be83f1ca436..ff3dd6bba8e 100644
--- a/engines/xeen/interface.h
+++ b/engines/mm/xeen/interface.h
@@ -23,12 +23,13 @@
#define XEEN_INTERFACE_H
#include "common/scummsys.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/interface_minimap.h"
-#include "xeen/interface_scene.h"
-#include "xeen/party.h"
-#include "xeen/window.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/interface_minimap.h"
+#include "mm/xeen/interface_scene.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/window.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -228,5 +229,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_INTERFACE_H */
+#endif
diff --git a/engines/xeen/interface_minimap.cpp b/engines/mm/xeen/interface_minimap.cpp
similarity index 99%
rename from engines/xeen/interface_minimap.cpp
rename to engines/mm/xeen/interface_minimap.cpp
index e8aba8542eb..606cbc36d49 100644
--- a/engines/xeen/interface_minimap.cpp
+++ b/engines/mm/xeen/interface_minimap.cpp
@@ -19,9 +19,10 @@
*
*/
-#include "xeen/interface_minimap.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/interface_minimap.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
#define MINIMAP_SIZE 7
@@ -434,3 +435,4 @@ void InterfaceMinimap::drawIndoorsMinimap() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/interface_minimap.h b/engines/mm/xeen/interface_minimap.h
similarity index 93%
rename from engines/xeen/interface_minimap.h
rename to engines/mm/xeen/interface_minimap.h
index afe640a3c91..d4f89e8283e 100644
--- a/engines/xeen/interface_minimap.h
+++ b/engines/mm/xeen/interface_minimap.h
@@ -22,6 +22,7 @@
#ifndef XEEN_INTERFACE_MINIMAP_H
#define XEEN_INTERFACE_MINIMAP_H
+namespace MM {
namespace Xeen {
class InterfaceMinimap {
@@ -38,7 +39,8 @@ private:
*/
void drawIndoorsMinimap();
public:
- InterfaceMinimap() : _animFrame(0) {}
+ InterfaceMinimap() : _animFrame(0) {
+ }
/**
* Draw the mini-map
@@ -47,5 +49,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_INTERFACE_MINIMAP_H */
+#endif
diff --git a/engines/xeen/interface_scene.cpp b/engines/mm/xeen/interface_scene.cpp
similarity index 99%
rename from engines/xeen/interface_scene.cpp
rename to engines/mm/xeen/interface_scene.cpp
index ee2e4435146..049b290795f 100644
--- a/engines/xeen/interface_scene.cpp
+++ b/engines/mm/xeen/interface_scene.cpp
@@ -19,11 +19,12 @@
*
*/
-#include "xeen/interface_scene.h"
-#include "xeen/dialogs/dialogs_message.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/interface_scene.h"
+#include "mm/xeen/dialogs/dialogs_message.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
static const int COMBAT_POS_X[3][2] = { { 102, 134 },{ 36, 67 },{ 161, 161 } };
@@ -4495,3 +4496,4 @@ void InterfaceScene::drawOutdoors() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/interface_scene.h b/engines/mm/xeen/interface_scene.h
similarity index 89%
rename from engines/xeen/interface_scene.h
rename to engines/mm/xeen/interface_scene.h
index 53ed3f53c68..648c15db26a 100644
--- a/engines/xeen/interface_scene.h
+++ b/engines/mm/xeen/interface_scene.h
@@ -23,9 +23,10 @@
#define XEEN_INTERFACE_SCENE_H
#include "common/scummsys.h"
-#include "xeen/map.h"
-#include "xeen/window.h"
+#include "mm/xeen/map.h"
+#include "mm/xeen/window.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -35,11 +36,11 @@ public:
DrawStruct _data[132];
DrawStruct &_sky1, &_sky2;
DrawStruct &_groundSprite;
- DrawStruct * const _groundTiles;
- DrawStruct * const _attackImgs1;
- DrawStruct * const _attackImgs2;
- DrawStruct * const _attackImgs3;
- DrawStruct * const _attackImgs4;
+ DrawStruct *const _groundTiles;
+ DrawStruct *const _attackImgs1;
+ DrawStruct *const _attackImgs2;
+ DrawStruct *const _attackImgs3;
+ DrawStruct *const _attackImgs4;
public:
/**
* Constructor
@@ -57,7 +58,9 @@ public:
/**
* Return the size of the list
*/
- int size() const { return 132; }
+ int size() const {
+ return 132;
+ }
/**
* Draw the list to the scene
@@ -71,7 +74,7 @@ public:
DrawStruct &_sky1, &_sky2;
DrawStruct &_ground;
DrawStruct &_horizon;
- DrawStruct * const _groundTiles;
+ DrawStruct *const _groundTiles;
DrawStruct &_swl_0F1R, &_swl_0F1L, &_swl_1F1R, &_swl_1F1L,
&_swl_2F2R, &_swl_2F1R, &_swl_2F1L, &_swl_2F2L,
&_swl_3F1R, &_swl_3F2R, &_swl_3F3R, &_swl_3F4R,
@@ -86,10 +89,10 @@ public:
DrawStruct &_objects0, &_objects1, &_objects2, &_objects3;
DrawStruct &_objects4, &_objects5, &_objects6, &_objects7;
DrawStruct &_objects8, &_objects9, &_objects10, &_objects11;
- DrawStruct * const _attackImgs1;
- DrawStruct * const _attackImgs2;
- DrawStruct * const _attackImgs3;
- DrawStruct * const _attackImgs4;
+ DrawStruct *const _attackImgs1;
+ DrawStruct *const _attackImgs2;
+ DrawStruct *const _attackImgs3;
+ DrawStruct *const _attackImgs4;
public:
IndoorDrawList();
@@ -104,7 +107,9 @@ public:
/**
* Return the size of the list
*/
- int size() const { return 170; }
+ int size() const {
+ return 170;
+ }
/**
* Draw the list to the scene
@@ -169,7 +174,8 @@ public:
public:
InterfaceScene(XeenEngine *vm);
- virtual ~InterfaceScene() {}
+ virtual ~InterfaceScene() {
+ }
/**
* Set up draw structures for displaying on-screen monsters
@@ -208,5 +214,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_INTERFACE_SCENE_H */
+#endif
diff --git a/engines/xeen/item.cpp b/engines/mm/xeen/item.cpp
similarity index 98%
rename from engines/xeen/item.cpp
rename to engines/mm/xeen/item.cpp
index be56cfbf177..763128efa4c 100644
--- a/engines/xeen/item.cpp
+++ b/engines/mm/xeen/item.cpp
@@ -19,11 +19,12 @@
*
*/
-#include "xeen/item.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-#include "xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/item.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+namespace MM {
namespace Xeen {
void ItemState::synchronize(Common::Serializer &s) {
@@ -120,8 +121,8 @@ const char *XeenItem::getItemName(ItemCategory category, uint id) {
/*------------------------------------------------------------------------*/
-InventoryItems::InventoryItems(Character *character, ItemCategory category):
- _character(character), _category(category) {
+InventoryItems::InventoryItems(Character *character, ItemCategory category) :
+ _character(character), _category(category) {
resize(INV_ITEMS_TOTAL);
_names = Res.ITEM_NAMES[category];
@@ -155,7 +156,8 @@ bool InventoryItems::passRestrictions(int itemId, bool suppressError) const {
case CLASS_NINJA:
case CLASS_BARBARIAN:
case CLASS_DRUID:
- case CLASS_RANGER: {
+ case CLASS_RANGER:
+ {
if (!(Res.ITEM_RESTRICTIONS[itemId + Res.RESTRICTION_OFFSETS[_category]] &
(1 << (charClass - CLASS_ARCHER))))
return true;
@@ -254,7 +256,7 @@ XeenEngine *InventoryItems::getVm() {
}
void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
- ItemCategory category2) {
+ ItemCategory category2) {
XeenEngine *vm = Party::_vm;
if (itemIndex1 >= 0) {
@@ -352,7 +354,7 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
XeenItem &i = operator[](itemIndex);
Common::String desc;
if (Common::RU_RUS == g_vm->getLanguage())
- desc = Common::String::format("\f%02u%s%s\f%02u%s%s%s%s", displayNum,
+ desc = Common::String::format("\f%02u%s%s\f%02u%s%s%s%s", displayNum,
i._state._broken ? Res.ITEM_BROKEN : "",
i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
@@ -535,7 +537,7 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
XeenItem &i = operator[](itemIndex);
Common::String desc;
- if (Common::RU_RUS == g_vm->getLanguage())
+ if (Common::RU_RUS == g_vm->getLanguage())
desc = Common::String::format("\f%02u%s%s\f%02u%s%s%s", displayNum,
i._state._broken ? Res.ITEM_BROKEN : "",
i._state._cursed ? Res.ITEM_CURSED : "",
@@ -665,7 +667,7 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum)
XeenItem &i = operator[](itemIndex);
Common::String desc;
- if (Common::RU_RUS == g_vm->getLanguage())
+ if (Common::RU_RUS == g_vm->getLanguage())
desc = Common::String::format("\f%02u%s%s\f%02u%s%s%s", displayNum,
i._state._broken ? Res.ITEM_BROKEN : "",
i._state._cursed ? Res.ITEM_CURSED : "",
@@ -812,3 +814,4 @@ bool InventoryItemsGroup::hasCursedItems() const {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/item.h b/engines/mm/xeen/item.h
similarity index 91%
rename from engines/xeen/item.h
rename to engines/mm/xeen/item.h
index 46ed41d66f9..125128216e1 100644
--- a/engines/xeen/item.h
+++ b/engines/mm/xeen/item.h
@@ -26,8 +26,9 @@
#include "common/array.h"
#include "common/rect.h"
#include "common/serializer.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
#define INV_ITEMS_TOTAL 9
@@ -68,7 +69,8 @@ struct ItemState {
/**
* Constructor
*/
- ItemState() : _counter(0), _cursed(false), _broken(false) {}
+ ItemState() : _counter(0), _cursed(false), _broken(false) {
+ }
/**
* Clear the state
@@ -81,7 +83,9 @@ struct ItemState {
/**
* Returns true if the state is empty
*/
- bool empty() const { return !_counter && !_cursed && !_broken; }
+ bool empty() const {
+ return !_counter && !_cursed && !_broken;
+ }
/**
* Synchronizes the item's state
@@ -119,17 +123,23 @@ public:
/**
* Returns true if no item is set
*/
- bool empty() const { return _id == 0; }
+ bool empty() const {
+ return _id == 0;
+ }
/**
* Returns true if the item is cursed or broken
*/
- bool isBad() const { return _state._cursed || _state._broken; }
+ bool isBad() const {
+ return _state._cursed || _state._broken;
+ }
/**
* Returns true for weapons if it's equipped
*/
- bool isEquipped() const { return _frame != 0; }
+ bool isEquipped() const {
+ return _frame != 0;
+ }
/**
* Synchronizes the data for the item
@@ -179,7 +189,8 @@ protected:
public:
InventoryItems(Character *character, ItemCategory category);
- virtual ~InventoryItems() {}
+ virtual ~InventoryItems() {
+ }
/**
* Clears the set of items
@@ -218,7 +229,8 @@ public:
/**
* Equips an item
*/
- virtual void equipItem(int itemIndex) {}
+ virtual void equipItem(int itemIndex) {
+ }
/**
* Un-equips the given item
@@ -241,15 +253,17 @@ public:
bool isFull() const;
};
-class WeaponItems: public InventoryItems {
+class WeaponItems : public InventoryItems {
protected:
/**
* Returns a text string listing all the stats/attributes of a given item
*/
Common::String getAttributes(XeenItem &item, const Common::String &classes) override;
public:
- WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
- ~WeaponItems() override {}
+ WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {
+ }
+ ~WeaponItems() override {
+ }
/**
* Equip a given weapon
@@ -280,8 +294,10 @@ protected:
*/
Common::String getAttributes(XeenItem &item, const Common::String &classes) override;
public:
- ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
- ~ArmorItems() override {}
+ ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {
+ }
+ ~ArmorItems() override {
+ }
/**
* Equip a given piece of armor
@@ -307,7 +323,8 @@ protected:
*/
Common::String getAttributes(XeenItem &item, const Common::String &classes) override;
public:
- AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {}
+ AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {
+ }
/**
* Equip a given accessory
@@ -328,8 +345,10 @@ protected:
*/
Common::String getAttributes(XeenItem &item, const Common::String &classes) override;
public:
- MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
- ~MiscItems() override {}
+ MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {
+ }
+ ~MiscItems() override {
+ }
/**
* Assembles a full lines description for a specified item for use in
@@ -342,7 +361,8 @@ class InventoryItemsGroup {
private:
Character *_owner;
public:
- InventoryItemsGroup(Character *owner) : _owner(owner) {}
+ InventoryItemsGroup(Character *owner) : _owner(owner) {
+ }
/**
* Returns the inventory items for a given category
@@ -371,5 +391,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_CHARACTER_H */
+#endif
diff --git a/engines/xeen/locations.cpp b/engines/mm/xeen/locations.cpp
similarity index 99%
rename from engines/xeen/locations.cpp
rename to engines/mm/xeen/locations.cpp
index 4201483c657..2b2295cd640 100644
--- a/engines/xeen/locations.cpp
+++ b/engines/mm/xeen/locations.cpp
@@ -19,17 +19,18 @@
*
*/
-#include "xeen/locations.h"
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/dialogs/dialogs_items.h"
-#include "xeen/dialogs/dialogs_party.h"
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/dialogs/dialogs_spells.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/locations.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/dialogs/dialogs_items.h"
+#include "mm/xeen/dialogs/dialogs_party.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/dialogs/dialogs_spells.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
#define WAIT(TIME) if (_subtitles.wait(TIME)) goto exit
+namespace MM {
namespace Xeen {
namespace Locations {
@@ -2466,3 +2467,4 @@ void LocationMessage::loadButtons() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/locations.h b/engines/mm/xeen/locations.h
similarity index 90%
rename from engines/xeen/locations.h
rename to engines/mm/xeen/locations.h
index dce2c55f4ad..d22a36577f2 100644
--- a/engines/xeen/locations.h
+++ b/engines/mm/xeen/locations.h
@@ -24,10 +24,11 @@
#include "common/scummsys.h"
#include "common/str-array.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/dialogs/dialogs_message.h"
-#include "xeen/party.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs_message.h"
+#include "mm/xeen/party.h"
+namespace MM {
namespace Xeen {
enum LocationAction {
@@ -63,7 +64,9 @@ protected:
/**
* Generates the display text for the location, for a given character
*/
- virtual Common::String createLocationText(Character &ch) { return ""; }
+ virtual Common::String createLocationText(Character &ch) {
+ return "";
+ }
/**
* Draw the visual background
@@ -73,12 +76,15 @@ protected:
/**
* Handles options for the particular location
*/
- virtual Character *doOptions(Character *c) { return c; }
+ virtual Character *doOptions(Character *c) {
+ return c;
+ }
/**
* Handle any farewell
*/
- virtual void farewell() {}
+ virtual void farewell() {
+ }
public:
BaseLocation(LocationAction action);
~BaseLocation() override;
@@ -122,7 +128,8 @@ protected:
Character *doOptions(Character *c) override;
public:
BankLocation();
- ~BankLocation() override {}
+ ~BankLocation() override {
+ }
};
class BlacksmithLocation : public BaseLocation {
@@ -143,7 +150,8 @@ protected:
Character *doOptions(Character *c) override;
public:
BlacksmithLocation();
- ~BlacksmithLocation() override {}
+ ~BlacksmithLocation() override {
+ }
};
class GuildLocation : public BaseLocation {
@@ -159,7 +167,8 @@ protected:
Character *doOptions(Character *c) override;
public:
GuildLocation();
- ~GuildLocation() override {}
+ ~GuildLocation() override {
+ }
};
class TavernLocation : public BaseLocation {
@@ -185,7 +194,8 @@ protected:
Character *doOptions(Character *c) override;
public:
TavernLocation();
- ~TavernLocation() override {}
+ ~TavernLocation() override {
+ }
};
class TempleLocation : public BaseLocation {
@@ -211,7 +221,8 @@ protected:
Character *doOptions(Character *c) override;
public:
TempleLocation();
- ~TempleLocation() override {}
+ ~TempleLocation() override {
+ }
};
class TrainingLocation : public BaseLocation {
@@ -236,13 +247,15 @@ protected:
Character *doOptions(Character *c) override;
public:
TrainingLocation();
- ~TrainingLocation() override {}
+ ~TrainingLocation() override {
+ }
};
class ArenaLocation : public BaseLocation {
public:
ArenaLocation();
- ~ArenaLocation() override {}
+ ~ArenaLocation() override {
+ }
/**
* Show the town location
@@ -274,7 +287,8 @@ private:
void getNewLocation();
public:
ReaperCutscene();
- ~ReaperCutscene() override {}
+ ~ReaperCutscene() override {
+ }
/**
* Show the town location
@@ -290,7 +304,8 @@ private:
void getNewLocation();
public:
GolemCutscene();
- ~GolemCutscene() override {}
+ ~GolemCutscene() override {
+ }
/**
* Show the town location
@@ -306,7 +321,8 @@ private:
void getNewLocation();
public:
DwarfCutscene();
- ~DwarfCutscene() override {}
+ ~DwarfCutscene() override {
+ }
/**
* Show the town location
@@ -322,7 +338,8 @@ private:
void getNewLocation();
public:
SphinxCutscene();
- ~SphinxCutscene() override {}
+ ~SphinxCutscene() override {
+ }
/**
* Show the town location
@@ -333,7 +350,8 @@ public:
class PyramidLocation : public BaseLocation {
public:
PyramidLocation();
- ~PyramidLocation() override {}
+ ~PyramidLocation() override {
+ }
/**
* Show the town location
@@ -347,7 +365,9 @@ class LocationMessage : public Locations::BaseLocation {
private:
SpriteResource _iconSprites;
- LocationMessage() : Locations::BaseLocation(NO_ACTION) { setWaitBounds(); }
+ LocationMessage() : Locations::BaseLocation(NO_ACTION) {
+ setWaitBounds();
+ }
bool execute(int portrait, const Common::String &name,
const Common::String &text, int confirm);
@@ -386,5 +406,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_LOCATIONS_H */
+#endif
diff --git a/engines/xeen/map.cpp b/engines/mm/xeen/map.cpp
similarity index 99%
rename from engines/xeen/map.cpp
rename to engines/mm/xeen/map.cpp
index 0e536165253..60bc67c7533 100644
--- a/engines/xeen/map.cpp
+++ b/engines/mm/xeen/map.cpp
@@ -20,14 +20,15 @@
*/
#include "common/serializer.h"
-#include "xeen/map.h"
-#include "xeen/interface.h"
-#include "xeen/resources.h"
-#include "xeen/saves.h"
-#include "xeen/screen.h"
-#include "xeen/xeen.h"
-#include "xeen/dialogs/please_wait.h"
-
+#include "mm/xeen/map.h"
+#include "mm/xeen/interface.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/saves.h"
+#include "mm/xeen/screen.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/dialogs/please_wait.h"
+
+namespace MM {
namespace Xeen {
static const int MAP_GRID_PRIOR_INDEX[] = { 0, 0, 0, 0, 1, 2, 3, 4, 0 };
@@ -1514,3 +1515,4 @@ Common::String Map::getMazeName(int mapId, int ccNum) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/map.h b/engines/mm/xeen/map.h
similarity index 93%
rename from engines/xeen/map.h
rename to engines/mm/xeen/map.h
index d24dfa35d83..bd9c9768c2b 100644
--- a/engines/xeen/map.h
+++ b/engines/mm/xeen/map.h
@@ -25,12 +25,13 @@
#include "common/stream.h"
#include "common/array.h"
#include "common/rect.h"
-#include "xeen/combat.h"
-#include "xeen/files.h"
-#include "xeen/party.h"
-#include "xeen/scripts.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/combat.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/scripts.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
#define MAP_WIDTH 16
@@ -154,7 +155,9 @@ enum MazeFlags {
FLAG_GROUND_BITS = 7
};
-enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 };
+enum MazeFlags2 {
+ FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000
+};
enum SurfaceType {
SURFTYPE_DEFAULT = 0,
@@ -185,7 +188,8 @@ union MazeWallLayers {
struct MazeCell {
int _flags;
int _surfaceId;
- MazeCell() : _flags(0), _surfaceId(0) {}
+ MazeCell() : _flags(0), _surfaceId(0) {
+ }
};
class MazeData {
@@ -317,13 +321,18 @@ public:
SpriteResource _sprites;
SpriteResource _attackSprites;
- SpriteResourceEntry() { _spriteId = -1; }
- SpriteResourceEntry(int spriteId): _spriteId(spriteId) { }
+ SpriteResourceEntry() {
+ _spriteId = -1;
+ }
+ SpriteResourceEntry(int spriteId) : _spriteId(spriteId) {
+ }
/**
* Returns true if no sprite id is specified
*/
- bool isEmpty() const { return _spriteId == -1; }
+ bool isEmpty() const {
+ return _spriteId == -1;
+ }
};
private:
XeenEngine *_vm;
@@ -366,11 +375,17 @@ public:
void synchronize(Common::SeekableReadStream &s);
- HeadEntry *operator[](int y) { return &_data[y][0]; }
+ HeadEntry *operator[](int y) {
+ return &_data[y][0];
+ }
};
-struct AnimationFrame { int _front, _left, _back, _right; };
-struct AnimationFlipped { bool _front, _left, _back, _right; };
+struct AnimationFrame {
+ int _front, _left, _back, _right;
+};
+struct AnimationFlipped {
+ bool _front, _left, _back, _right;
+};
struct AnimationEntry {
union {
AnimationFrame _positions;
@@ -506,17 +521,23 @@ public:
/**
* Returns the data for the primary active map
*/
- MazeData &mazeData() { return _mazeData[0]; }
+ MazeData &mazeData() {
+ return _mazeData[0];
+ }
/**
* Returns the data for the primary active map
*/
- const MazeData *mazeDataSurrounding() { return _mazeData; }
+ const MazeData *mazeDataSurrounding() {
+ return _mazeData;
+ }
/**
* Returns the data for the currently indexed map
*/
- MazeData &mazeDataCurrent() { return _mazeData[_mazeDataIndex]; }
+ MazeData &mazeDataCurrent() {
+ return _mazeData[_mazeDataIndex];
+ }
/**
* Loads the sprites needed for rendering the skyline
@@ -539,5 +560,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_MAP_H */
+#endif
diff --git a/engines/xeen/party.cpp b/engines/mm/xeen/party.cpp
similarity index 99%
rename from engines/xeen/party.cpp
rename to engines/mm/xeen/party.cpp
index 0d847786051..2a25234c320 100644
--- a/engines/xeen/party.cpp
+++ b/engines/mm/xeen/party.cpp
@@ -21,15 +21,16 @@
#include "common/scummsys.h"
#include "common/algorithm.h"
-#include "xeen/party.h"
-#include "xeen/dialogs/dialogs_message.h"
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/files.h"
-#include "xeen/resources.h"
-#include "xeen/saves.h"
-#include "xeen/spells.h"
-#include "xeen/xeen.h"
-
+#include "mm/xeen/party.h"
+#include "mm/xeen/dialogs/dialogs_message.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/saves.h"
+#include "mm/xeen/spells.h"
+#include "mm/xeen/xeen.h"
+
+namespace MM {
namespace Xeen {
/*------------------------------------------------------------------------*/
@@ -1640,3 +1641,4 @@ uint Party::getScore() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/party.h b/engines/mm/xeen/party.h
similarity index 95%
rename from engines/xeen/party.h
rename to engines/mm/xeen/party.h
index b9b9e803892..e52a94f167e 100644
--- a/engines/xeen/party.h
+++ b/engines/mm/xeen/party.h
@@ -26,17 +26,20 @@
#include "common/array.h"
#include "common/rect.h"
#include "common/serializer.h"
-#include "xeen/character.h"
-#include "xeen/combat.h"
-#include "xeen/dialogs/dialogs_message.h"
+#include "mm/xeen/character.h"
+#include "mm/xeen/combat.h"
+#include "mm/xeen/dialogs/dialogs_message.h"
+namespace MM {
namespace Xeen {
enum Direction {
DIR_NORTH = 0, DIR_EAST = 1, DIR_SOUTH = 2, DIR_WEST = 3, DIR_ALL = 4
};
-enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
+enum Difficulty {
+ ADVENTURER = 0, WARRIOR = 1
+};
enum ConsumableType {
CONS_GOLD = 0, CONS_GEMS = 1, CONS_FOOD = 2, CONS_CONDITION = 3
@@ -56,7 +59,7 @@ enum PartyBank {
#define TOTAL_QUEST_FLAGS 56
#define MAX_TREASURE_ITEMS 10
-class Roster: public Common::Array<Character> {
+class Roster : public Common::Array<Character> {
public:
SpriteResource _charFaces[TOTAL_CHARACTERS];
public:
@@ -80,7 +83,9 @@ public:
/**
* Returns a particular category's array
*/
- XeenItem *operator[](int category) { return _categories[category]; }
+ XeenItem *operator[](int category) {
+ return _categories[category];
+ }
/**
* Clears the treasure list
@@ -114,7 +119,9 @@ public:
/**
* Constructor
*/
- BlacksmithWares() { clear(); }
+ BlacksmithWares() {
+ clear();
+ }
/**
* Clear all current blacksmith wares
@@ -328,5 +335,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_PARTY_H */
+#endif
diff --git a/engines/xeen/patcher.cpp b/engines/mm/xeen/patcher.cpp
similarity index 95%
rename from engines/xeen/patcher.cpp
rename to engines/mm/xeen/patcher.cpp
index dcf1ac2a10b..d956291dc58 100644
--- a/engines/xeen/patcher.cpp
+++ b/engines/mm/xeen/patcher.cpp
@@ -19,13 +19,14 @@
*
*/
-#include "xeen/patcher.h"
-#include "xeen/xeen.h"
-#include "xeen/map.h"
-#include "xeen/party.h"
+#include "mm/xeen/patcher.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/map.h"
+#include "mm/xeen/party.h"
#include "common/memstream.h"
#include "common/serializer.h"
+namespace MM {
namespace Xeen {
struct ScriptEntry {
@@ -98,7 +99,7 @@ void Patcher::patchScripts() {
// Scan through the events to find a matching line
int idx = 0;
while (idx < (int)map._events.size() && (evt._position != map._events[idx]._position
- || evt._direction != map._events[idx]._direction || evt._line != map._events[idx]._line))
+ || evt._direction != map._events[idx]._direction || evt._line != map._events[idx]._line))
++idx;
// Set the event
@@ -144,3 +145,4 @@ void Patcher::patchObjects() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/patcher.h b/engines/mm/xeen/patcher.h
similarity index 95%
rename from engines/xeen/patcher.h
rename to engines/mm/xeen/patcher.h
index 3aca8f3eb97..d3017866c4c 100644
--- a/engines/xeen/patcher.h
+++ b/engines/mm/xeen/patcher.h
@@ -22,6 +22,7 @@
#ifndef XEEN_PATCHER_H
#define XEEN_PATCHER_H
+namespace MM {
namespace Xeen {
class Patcher {
@@ -39,7 +40,8 @@ public:
/**
* Constructor
*/
- Patcher() {}
+ Patcher() {
+ }
/**
* Called after a map is loaded to patch any problems
@@ -48,5 +50,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_PATCHER_H */
+#endif
diff --git a/engines/xeen/resources.cpp b/engines/mm/xeen/resources.cpp
similarity index 99%
rename from engines/xeen/resources.cpp
rename to engines/mm/xeen/resources.cpp
index e830d11491d..9df42be8a1a 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/mm/xeen/resources.cpp
@@ -20,10 +20,11 @@
*/
#include "common/scummsys.h"
-#include "xeen/resources.h"
-#include "xeen/files.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
Resources *g_resources;
@@ -514,3 +515,4 @@ void Resources::loadData() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/resources.h b/engines/mm/xeen/resources.h
similarity index 98%
rename from engines/xeen/resources.h
rename to engines/mm/xeen/resources.h
index 6fe635a8aad..3409d3c7a3a 100644
--- a/engines/xeen/resources.h
+++ b/engines/mm/xeen/resources.h
@@ -25,10 +25,11 @@
#include "common/scummsys.h"
#include "common/str-array.h"
#include "gui/debugger.h"
-#include "xeen/files.h"
-#include "xeen/party.h"
-#include "xeen/spells.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/spells.h"
+namespace MM {
namespace Xeen {
#define Res (*g_resources)
@@ -47,7 +48,8 @@ class Resources {
char *_buffer;
char *_buffStart;
public:
- ResFile(const char* type, char *buffer, int num) : File(type + Common::String::format("%i", num)), _buffer(buffer), _buffStart(buffer) {}
+ ResFile(const char *type, char *buffer, int num) : File(type + Common::String::format("%i", num)), _buffer(buffer), _buffStart(buffer) {
+ }
void syncString(const char *&str) {
str = _buffer;
@@ -604,5 +606,6 @@ public:
extern Resources *g_resources;
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_RESOURCES_H */
+#endif
diff --git a/engines/xeen/saves.cpp b/engines/mm/xeen/saves.cpp
similarity index 96%
rename from engines/xeen/saves.cpp
rename to engines/mm/xeen/saves.cpp
index e8e4827b579..1584c7b9a27 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/mm/xeen/saves.cpp
@@ -27,14 +27,15 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gui/saveload.h"
-#include "xeen/saves.h"
-#include "xeen/files.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/saves.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
-SavesManager::SavesManager(const Common::String &targetName): _targetName(targetName),
- _wonWorld(false), _wonDarkSide(false) {
+SavesManager::SavesManager(const Common::String &targetName) : _targetName(targetName),
+_wonWorld(false), _wonDarkSide(false) {
File::_xeenSave = nullptr;
File::_darkSave = nullptr;
}
@@ -291,3 +292,4 @@ void SavesManager::doAutosave() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/saves.h b/engines/mm/xeen/saves.h
similarity index 97%
rename from engines/xeen/saves.h
rename to engines/mm/xeen/saves.h
index 93185651fae..e6ccc1905ef 100644
--- a/engines/xeen/saves.h
+++ b/engines/mm/xeen/saves.h
@@ -27,8 +27,9 @@
#include "common/serializer.h"
#include "common/str.h"
#include "graphics/surface.h"
-#include "xeen/party.h"
+#include "mm/xeen/party.h"
+namespace MM {
namespace Xeen {
enum {
@@ -103,5 +104,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SAVES_H */
+#endif
diff --git a/engines/xeen/screen.cpp b/engines/mm/xeen/screen.cpp
similarity index 96%
rename from engines/xeen/screen.cpp
rename to engines/mm/xeen/screen.cpp
index 0d4dc1faa77..541905219f8 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/mm/xeen/screen.cpp
@@ -22,11 +22,12 @@
#include "common/system.h"
#include "graphics/palette.h"
#include "graphics/surface.h"
-#include "xeen/screen.h"
-#include "xeen/resources.h"
-#include "xeen/window.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/screen.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/window.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
Screen::Screen(XeenEngine *vm) : _vm(vm) {
@@ -192,7 +193,7 @@ bool Screen::doScroll(bool rollUp, bool fadeInFlag) {
if (rollUp) {
for (int i = 22, ctr = 7; i > 0 && !events.isKeyMousePressed()
- && !_vm->shouldExit(); --i) {
+ && !_vm->shouldExit(); --i) {
events.updateGameCounter();
screen.restoreBackground();
@@ -216,7 +217,7 @@ bool Screen::doScroll(bool rollUp, bool fadeInFlag) {
}
} else {
for (int i = 0, ctr = 0; i < 22 && !events.isKeyMousePressed()
- && !_vm->shouldExit(); ++i) {
+ && !_vm->shouldExit(); ++i) {
events.updateGameCounter();
screen.restoreBackground();
@@ -259,3 +260,4 @@ bool Screen::doScroll(bool rollUp, bool fadeInFlag) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/screen.h b/engines/mm/xeen/screen.h
similarity index 91%
rename from engines/xeen/screen.h
rename to engines/mm/xeen/screen.h
index 138e25c27b4..fb34e83c2ce 100644
--- a/engines/xeen/screen.h
+++ b/engines/mm/xeen/screen.h
@@ -24,9 +24,10 @@
#include "common/rect.h"
#include "graphics/screen.h"
-#include "xeen/font.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/font.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
#define SCREEN_WIDTH 320
@@ -36,7 +37,7 @@ namespace Xeen {
class XeenEngine;
-class Screen: public Graphics::Screen {
+class Screen : public Graphics::Screen {
private:
XeenEngine *_vm;
byte _mainPalette[PALETTE_SIZE];
@@ -57,13 +58,16 @@ private:
void updatePalette(const byte *pal, int start, int count16);
public:
Screen(XeenEngine *vm);
- ~Screen() override {}
+ ~Screen() override {
+ }
/**
* Base method that descendent classes can override for recording affected
* dirty areas of the surface
*/
- void addDirtyRect(const Common::Rect &r) override { Graphics::Screen::addDirtyRect(r); }
+ void addDirtyRect(const Common::Rect &r) override {
+ Graphics::Screen::addDirtyRect(r);
+ }
/**
* Load a palette resource into the temporary palette
@@ -122,5 +126,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SCREEN_H */
+#endif
diff --git a/engines/xeen/scripts.cpp b/engines/mm/xeen/scripts.cpp
similarity index 99%
rename from engines/xeen/scripts.cpp
rename to engines/mm/xeen/scripts.cpp
index db5348ea49a..cac59f9959f 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/mm/xeen/scripts.cpp
@@ -22,15 +22,16 @@
#include "common/config-manager.h"
#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
-#include "xeen/scripts.h"
-#include "xeen/dialogs/dialogs_copy_protection.h"
-#include "xeen/dialogs/dialogs_input.h"
-#include "xeen/dialogs/dialogs_whowill.h"
-#include "xeen/dialogs/dialogs_query.h"
-#include "xeen/party.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-
+#include "mm/xeen/scripts.h"
+#include "mm/xeen/dialogs/dialogs_copy_protection.h"
+#include "mm/xeen/dialogs/dialogs_input.h"
+#include "mm/xeen/dialogs/dialogs_whowill.h"
+#include "mm/xeen/dialogs/dialogs_query.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+
+namespace MM {
namespace Xeen {
byte EventParameters::Iterator::readByte() {
@@ -1966,3 +1967,4 @@ void Scripts::display(bool justifyFlag, int var46) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/scripts.h b/engines/mm/xeen/scripts.h
similarity index 82%
rename from engines/xeen/scripts.h
rename to engines/mm/xeen/scripts.h
index 488aff52b8b..ed5d1f81955 100644
--- a/engines/xeen/scripts.h
+++ b/engines/mm/xeen/scripts.h
@@ -27,73 +27,74 @@
#include "common/serializer.h"
#include "common/stack.h"
#include "common/str-array.h"
-#include "xeen/files.h"
-#include "xeen/party.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/party.h"
+namespace MM {
namespace Xeen {
enum Opcode {
- OP_None = 0x00,
- OP_Display0x01 = 0x01,
- OP_DoorTextSml = 0x02,
- OP_DoorTextLrg = 0x03,
- OP_SignText = 0x04,
- OP_NPC = 0x05,
- OP_PlayFX = 0x06,
- OP_TeleportAndExit = 0x07,
- OP_If1 = 0x08,
- OP_If2 = 0x09,
- OP_If3 = 0x0A,
- OP_MoveObj = 0x0B,
- OP_TakeOrGive = 0x0C,
- OP_NoAction = 0x0D,
- OP_Remove = 0x0E,
- OP_SetChar = 0x0F,
- OP_Spawn = 0x10,
- OP_DoTownEvent = 0x11,
- OP_Exit = 0x12,
- OP_AfterMap = 0x13,
- OP_GiveMulti = 0x14,
- OP_ConfirmWord = 0x15,
- OP_Damage = 0x16,
- OP_JumpRnd = 0x17,
- OP_AfterEvent = 0x18,
- OP_CallEvent = 0x19,
- OP_Return = 0x1A,
- OP_SetVar = 0x1B,
- OP_TakeOrGive_2 = 0x1C,
- OP_TakeOrGive_3 = 0x1D,
- OP_CutsceneEndClouds = 0x1E,
- OP_TeleportAndContinue = 0x1F,
- OP_WhoWill = 0x20,
- OP_RndDamage = 0x21,
- OP_MoveWallObj = 0x22,
- OP_AlterCellFlag = 0x23,
- OP_AlterHed = 0x24,
- OP_DisplayStat = 0x25,
- OP_TakeOrGive_4 = 0x26,
- OP_SeatTextSml = 0x27,
- OP_PlayEventVoc = 0x28,
- OP_DisplayBottom = 0x29,
- OP_IfMapFlag = 0x2A,
- OP_SelectRandomChar = 0x2B,
- OP_GiveEnchanted = 0x2C,
- OP_ItemType = 0x2D,
- OP_MakeNothingHere = 0x2E,
- OP_NoAction_2 = 0x2F,
- OP_ChooseNumeric = 0x30,
+ OP_None = 0x00,
+ OP_Display0x01 = 0x01,
+ OP_DoorTextSml = 0x02,
+ OP_DoorTextLrg = 0x03,
+ OP_SignText = 0x04,
+ OP_NPC = 0x05,
+ OP_PlayFX = 0x06,
+ OP_TeleportAndExit = 0x07,
+ OP_If1 = 0x08,
+ OP_If2 = 0x09,
+ OP_If3 = 0x0A,
+ OP_MoveObj = 0x0B,
+ OP_TakeOrGive = 0x0C,
+ OP_NoAction = 0x0D,
+ OP_Remove = 0x0E,
+ OP_SetChar = 0x0F,
+ OP_Spawn = 0x10,
+ OP_DoTownEvent = 0x11,
+ OP_Exit = 0x12,
+ OP_AfterMap = 0x13,
+ OP_GiveMulti = 0x14,
+ OP_ConfirmWord = 0x15,
+ OP_Damage = 0x16,
+ OP_JumpRnd = 0x17,
+ OP_AfterEvent = 0x18,
+ OP_CallEvent = 0x19,
+ OP_Return = 0x1A,
+ OP_SetVar = 0x1B,
+ OP_TakeOrGive_2 = 0x1C,
+ OP_TakeOrGive_3 = 0x1D,
+ OP_CutsceneEndClouds = 0x1E,
+ OP_TeleportAndContinue = 0x1F,
+ OP_WhoWill = 0x20,
+ OP_RndDamage = 0x21,
+ OP_MoveWallObj = 0x22,
+ OP_AlterCellFlag = 0x23,
+ OP_AlterHed = 0x24,
+ OP_DisplayStat = 0x25,
+ OP_TakeOrGive_4 = 0x26,
+ OP_SeatTextSml = 0x27,
+ OP_PlayEventVoc = 0x28,
+ OP_DisplayBottom = 0x29,
+ OP_IfMapFlag = 0x2A,
+ OP_SelectRandomChar = 0x2B,
+ OP_GiveEnchanted = 0x2C,
+ OP_ItemType = 0x2D,
+ OP_MakeNothingHere = 0x2E,
+ OP_NoAction_2 = 0x2F,
+ OP_ChooseNumeric = 0x30,
OP_DisplayBottomTwoLines = 0x31,
- OP_DisplayLarge = 0x32,
- OP_ExchObj = 0x33,
- OP_FallToMap = 0x34,
- OP_DisplayMain = 0x35,
- OP_Goto = 0x36,
- OP_ConfirmWord_2 = 0x37,
- OP_GotoRandom = 0x38,
- OP_CutsceneEndDarkside = 0x39,
- OP_CutsceneEdWorld = 0x3A,
- OP_FlipWorld = 0x3B,
- OP_PlayCD = 0x3C
+ OP_DisplayLarge = 0x32,
+ OP_ExchObj = 0x33,
+ OP_FallToMap = 0x34,
+ OP_DisplayMain = 0x35,
+ OP_Goto = 0x36,
+ OP_ConfirmWord_2 = 0x37,
+ OP_GotoRandom = 0x38,
+ OP_CutsceneEndDarkside = 0x39,
+ OP_CutsceneEdWorld = 0x3A,
+ OP_FlipWorld = 0x3B,
+ OP_PlayCD = 0x3C
};
enum {
@@ -113,8 +114,10 @@ public:
uint _index;
const EventParameters &_data;
public:
- Iterator(const EventParameters &owner) : _data(owner), _index(0) {}
- Iterator(const Iterator &it) : _data(it._data), _index(0) {}
+ Iterator(const EventParameters &owner) : _data(owner), _index(0) {
+ }
+ Iterator(const Iterator &it) : _data(it._data), _index(0) {
+ }
/**
* Return a byte
@@ -124,7 +127,9 @@ public:
/**
* Return a signed byte
*/
- int8 readShort() { return (int8)readByte(); }
+ int8 readShort() {
+ return (int8)readByte();
+ }
/**
* Return a word
@@ -183,7 +188,8 @@ public:
struct StackEntry : public Common::Point {
int line;
- StackEntry(const Common::Point &pt, int l) : Common::Point(pt), line(l) {}
+ StackEntry(const Common::Point &pt, int l) : Common::Point(pt), line(l) {
+ }
};
/**
@@ -195,7 +201,8 @@ struct MirrorEntry {
Common::Point _position;
int _direction;
- MirrorEntry() : _mapId(0), _direction(DIR_ALL) {}
+ MirrorEntry() : _mapId(0), _direction(DIR_ALL) {
+ }
bool synchronize(Common::SeekableReadStream &s);
};
@@ -572,5 +579,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SCRIPTS_H */
+#endif
diff --git a/engines/xeen/sound.cpp b/engines/mm/xeen/sound.cpp
similarity index 96%
rename from engines/xeen/sound.cpp
rename to engines/mm/xeen/sound.cpp
index 376758f73da..d9fbddbbfb2 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/mm/xeen/sound.cpp
@@ -23,15 +23,16 @@
#include "audio/decoders/voc.h"
#include "backends/audiocd/audiocd.h"
#include "common/config-manager.h"
-#include "xeen/sound.h"
-#include "xeen/sound_driver_adlib.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/sound.h"
+#include "mm/xeen/sound_driver_adlib.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer), _fxOn(true), _musicOn(true), _subtitles(false),
- _songData(nullptr), _effectsData(nullptr), _musicSide(0), _musicPercent(100),
- _musicVolume(0), _sfxVolume(0) {
+_songData(nullptr), _effectsData(nullptr), _musicSide(0), _musicPercent(100),
+_musicVolume(0), _sfxVolume(0) {
_SoundDriver = new SoundDriverAdlib();
if (g_vm->getIsCD())
g_system->getAudioCDManager()->open();
@@ -250,3 +251,4 @@ void Sound::updateVolume() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/sound.h b/engines/mm/xeen/sound.h
similarity index 95%
rename from engines/xeen/sound.h
rename to engines/mm/xeen/sound.h
index f191d40d94b..22612bfdd93 100644
--- a/engines/xeen/sound.h
+++ b/engines/mm/xeen/sound.h
@@ -24,12 +24,12 @@
#include "audio/mixer.h"
#include "audio/audiostream.h"
-#include "xeen/files.h"
-#include "xeen/sound_driver.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/sound_driver.h"
+namespace MM {
namespace Xeen {
-
class Sound {
private:
SoundDriver *_SoundDriver;
@@ -83,7 +83,9 @@ public:
/**
* Stops any currently playing music
*/
- void stopSong() { songCommand(STOP_SONG); }
+ void stopSong() {
+ songCommand(STOP_SONG);
+ }
/**
* Sets the in-game music volume percent. This is separate from the ScummVM volume
@@ -159,5 +161,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SOUND_H */
+#endif
diff --git a/engines/xeen/sound_driver.cpp b/engines/mm/xeen/sound_driver.cpp
similarity index 97%
rename from engines/xeen/sound_driver.cpp
rename to engines/mm/xeen/sound_driver.cpp
index 044343f5bf4..fbab864cca1 100644
--- a/engines/xeen/sound_driver.cpp
+++ b/engines/mm/xeen/sound_driver.cpp
@@ -21,10 +21,11 @@
#include "common/md5.h"
#include "common/config-manager.h"
-#include "xeen/sound_driver.h"
-#include "xeen/xeen.h"
-#include "xeen/files.h"
+#include "mm/xeen/sound_driver.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/files.h"
+namespace MM {
namespace Xeen {
SoundDriver::SoundDriver() : _frameCtr(0) {
@@ -38,7 +39,7 @@ SoundDriver::~SoundDriver() {
SoundDriver::Stream *SoundDriver::tickStream() {
for (size_t i = 0; i < stLAST; ++i) {
- Stream& stream = _streams[i];
+ Stream &stream = _streams[i];
if (stream._playing && (stream._countdownTimer == 0 || --stream._countdownTimer == 0))
return &stream;
}
@@ -238,3 +239,4 @@ const CommandFn SoundDriver::FX_COMMANDS[16] = {
};
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/sound_driver.h b/engines/mm/xeen/sound_driver.h
similarity index 93%
rename from engines/xeen/sound_driver.h
rename to engines/mm/xeen/sound_driver.h
index 3cb01114155..ed3f25d745f 100644
--- a/engines/xeen/sound_driver.h
+++ b/engines/mm/xeen/sound_driver.h
@@ -28,7 +28,7 @@
#include "common/mutex.h"
#include "common/queue.h"
#include "common/stack.h"
-#include "xeen/files.h"
+#include "mm/xeen/files.h"
#define CHANNEL_COUNT 9
@@ -36,6 +36,7 @@ namespace OPL {
class OPL;
}
+namespace MM {
namespace Xeen {
enum MusicCommand {
@@ -44,7 +45,7 @@ enum MusicCommand {
class SoundDriver;
-typedef bool (SoundDriver::*CommandFn)(const byte *&srcP, byte param);
+typedef bool (SoundDriver:: *CommandFn)(const byte *&srcP, byte param);
/**
* Base class for sound drivers
@@ -54,9 +55,11 @@ protected:
struct Subroutine {
const byte *_returnP;
const byte *_jumpP;
- Subroutine() : _returnP(nullptr), _jumpP(nullptr) {}
+ Subroutine() : _returnP(nullptr), _jumpP(nullptr) {
+ }
Subroutine(const byte *returnP, const byte *endP) :
- _returnP(returnP), _jumpP(endP) {}
+ _returnP(returnP), _jumpP(endP) {
+ }
};
struct Channel {
bool _changeFrequency;
@@ -68,7 +71,8 @@ protected:
bool _isFx;
uint _frequency;
Channel() : _changeFrequency(false), _freqCtr(0), _freqCtrChange(0),
- _freqChange(0), _volume(0), _totalLevel(0), _frequency(0), _isFx(false) {}
+ _freqChange(0), _volume(0), _totalLevel(0), _frequency(0), _isFx(false) {
+ }
};
enum StreamType {
stMUSIC,
@@ -78,8 +82,10 @@ protected:
};
class Stream {
public:
- Stream() {}
- Stream(const CommandFn *commands) : _playing(false), _countdownTimer(0), _dataPtr(nullptr), _startPtr(nullptr), _commands(commands) {}
+ Stream() {
+ }
+ Stream(const CommandFn *commands) : _playing(false), _countdownTimer(0), _dataPtr(nullptr), _startPtr(nullptr), _commands(commands) {
+ }
bool _playing;
int _countdownTimer;
@@ -188,9 +194,12 @@ public:
/**
* Returns whether music is currently playing
*/
- bool isPlaying() const { return _streams[stMUSIC]._playing; }
+ bool isPlaying() const {
+ return _streams[stMUSIC]._playing;
+ }
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SOUND_DRIVER_H */
+#endif
diff --git a/engines/xeen/sound_driver_adlib.cpp b/engines/mm/xeen/sound_driver_adlib.cpp
similarity index 98%
rename from engines/xeen/sound_driver_adlib.cpp
rename to engines/mm/xeen/sound_driver_adlib.cpp
index b9efeefc5c9..a0b06ca2b89 100644
--- a/engines/xeen/sound_driver_adlib.cpp
+++ b/engines/mm/xeen/sound_driver_adlib.cpp
@@ -19,9 +19,10 @@
*
*/
-#include "xeen/sound_driver_adlib.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/sound_driver_adlib.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
#define CALLBACKS_PER_SECOND 73
@@ -43,7 +44,7 @@ const uint SoundDriverAdlib::WAVEFORMS[24] = {
/*------------------------------------------------------------------------*/
SoundDriverAdlib::SoundDriverAdlib() : _field180(0), _field181(0), _field182(0),
- _musicVolume(0), _sfxVolume(0) {
+_musicVolume(0), _sfxVolume(0) {
Common::fill(&_musInstrumentPtrs[0], &_musInstrumentPtrs[16], (const byte *)nullptr);
Common::fill(&_fxInstrumentPtrs[0], &_fxInstrumentPtrs[16], (const byte *)nullptr);
@@ -424,3 +425,4 @@ byte SoundDriverAdlib::calculateLevel(byte level, bool isFx) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/sound_driver_adlib.h b/engines/mm/xeen/sound_driver_adlib.h
similarity index 98%
rename from engines/xeen/sound_driver_adlib.h
rename to engines/mm/xeen/sound_driver_adlib.h
index b0f28983b4c..eb9708230e5 100644
--- a/engines/xeen/sound_driver_adlib.h
+++ b/engines/mm/xeen/sound_driver_adlib.h
@@ -22,12 +22,13 @@
#ifndef XEEN_SOUND_DRIVER_ADLIB_H
#define XEEN_SOUND_DRIVER_ADLIB_H
-#include "xeen/sound_driver.h"
+#include "mm/xeen/sound_driver.h"
namespace OPL {
class OPL;
}
+namespace MM {
namespace Xeen {
class SoundDriverAdlib : public SoundDriver {
@@ -162,5 +163,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SOUND_DRIVER_H */
+#endif
diff --git a/engines/xeen/spells.cpp b/engines/mm/xeen/spells.cpp
similarity index 99%
rename from engines/xeen/spells.cpp
rename to engines/mm/xeen/spells.cpp
index e7c4a8fab87..42dd97b79b2 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/mm/xeen/spells.cpp
@@ -19,13 +19,14 @@
*
*/
-#include "xeen/spells.h"
-#include "xeen/dialogs/dialogs_items.h"
-#include "xeen/dialogs/dialogs_spells.h"
-#include "xeen/files.h"
-#include "xeen/resources.h"
-#include "xeen/xeen.h"
-
+#include "mm/xeen/spells.h"
+#include "mm/xeen/dialogs/dialogs_items.h"
+#include "mm/xeen/dialogs/dialogs_spells.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/xeen.h"
+
+namespace MM {
namespace Xeen {
Spells::Spells(XeenEngine *vm) : _vm(vm) {
@@ -1300,3 +1301,4 @@ void Spells::frostbite2() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/spells.h b/engines/mm/xeen/spells.h
similarity index 97%
rename from engines/xeen/spells.h
rename to engines/mm/xeen/spells.h
index 341c9fa7147..9f4e0e5e9f5 100644
--- a/engines/xeen/spells.h
+++ b/engines/mm/xeen/spells.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "common/str-array.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -32,7 +33,7 @@ class Character;
enum MagicSpell {
MS_AcidSpray = 0, MS_Awaken = 1, MS_BeastMaster = 2, MS_Bless = 3,
- MS_Clairvoyance = 4, MS_ColdRay = 5, MS_CreateFood = 6,
+ MS_Clairvoyance = 4, MS_ColdRay = 5, MS_CreateFood = 6,
MS_CureDisease = 7, MS_CureParalysis = 8, MS_CurePoison = 9,
MS_CureWounds = 10, MS_DancingSword = 11, MS_DayOfProtection = 12,
MS_DayOfSorcery = 13, MS_DeadlySwarm = 14, MS_DetectMonster = 15,
@@ -184,5 +185,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SPELLS_H */
+#endif
diff --git a/engines/xeen/sprites.cpp b/engines/mm/xeen/sprites.cpp
similarity index 98%
rename from engines/xeen/sprites.cpp
rename to engines/mm/xeen/sprites.cpp
index 6a88aeeda5a..2eec03bebc1 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/mm/xeen/sprites.cpp
@@ -23,12 +23,13 @@
#include "common/archive.h"
#include "common/memstream.h"
#include "common/textconsole.h"
-#include "xeen/xeen.h"
-#include "xeen/screen.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/screen.h"
+#include "mm/xeen/sprites.h"
#include "graphics/palette.h"
+namespace MM {
namespace Xeen {
#define SCENE_CLIP_LEFT 8
@@ -116,23 +117,23 @@ void SpriteResource::clear() {
}
void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos,
- uint flags, int scale) {
+ uint flags, int scale) {
draw(dest, frame, destPos, Common::Rect(0, 0, dest.w, dest.h), flags, scale);
}
void SpriteResource::draw(Window &dest, int frame, const Common::Point &destPos,
- uint flags, int scale) {
+ uint flags, int scale) {
draw(dest, frame, destPos, dest.getBounds(), flags, scale);
}
void SpriteResource::draw(int windowIndex, int frame, const Common::Point &destPos,
- uint flags, int scale) {
+ uint flags, int scale) {
Window &win = (*g_vm->_windows)[windowIndex];
draw(win, frame, destPos, flags, scale);
}
void SpriteResource::draw(XSurface &dest, int frame, const Common::Point &destPos,
- const Common::Rect &bounds, uint flags, int scale) {
+ const Common::Rect &bounds, uint flags, int scale) {
Common::Rect r = bounds;
if (flags & SPRFLAG_BOTTOM_CLIPPED)
r.clip(SCREEN_WIDTH, _clippedBottom);
@@ -200,7 +201,7 @@ Common::Point SpriteResource::getFrameSize(int frame) const {
/*------------------------------------------------------------------------*/
void SpriteDrawer::draw(XSurface &dest, uint16 offset, const Common::Point &pt,
- const Common::Rect &clipRect, uint flags, int scale) {
+ const Common::Rect &clipRect, uint flags, int scale) {
static const uint SCALE_TABLE[] = {
0xFFFF, 0xFFEF, 0xEFEF, 0xEFEE, 0xEEEE, 0xEEAE, 0xAEAE, 0xAEAA,
0xAAAA, 0xAA8A, 0x8A8A, 0x8A88, 0x8888, 0x8880, 0x8080, 0x8000
@@ -541,7 +542,7 @@ void SpriteDrawer3::drawPixel(byte *dest, byte pixel) {
//
while (*dest < 0xff && !_palette[*dest * 3] && !_palette[*dest * 3 + 1] && !_palette[*dest * 3 + 2])
- ++*dest;
+ ++ *dest;
}
}
@@ -593,3 +594,4 @@ void SpriteDrawer6::drawPixel(byte *dest, byte pixel) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/sprites.h b/engines/mm/xeen/sprites.h
similarity index 96%
rename from engines/xeen/sprites.h
rename to engines/mm/xeen/sprites.h
index e8497e8a803..2f0d81838be 100644
--- a/engines/xeen/sprites.h
+++ b/engines/mm/xeen/sprites.h
@@ -26,9 +26,10 @@
#include "common/array.h"
#include "common/file.h"
#include "graphics/surface.h"
-#include "xeen/files.h"
-#include "xeen/xsurface.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/xsurface.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -163,18 +164,24 @@ public:
/**
* Returns the number of frames the sprite resource has
*/
- size_t size() const { return _index.size(); }
+ size_t size() const {
+ return _index.size();
+ }
/**
* Returns true if the sprite resource is empty (ie. nothing is loaded)
*/
- bool empty() const { return _index.size() == 0; }
+ bool empty() const {
+ return _index.size() == 0;
+ }
/**
* Set the bottom Y position where sprites are clipped if SPRFLAG_BOTTOM_CLIPPED
* is applied
*/
- static void setClippedBottom(int y) { _clippedBottom = y; }
+ static void setClippedBottom(int y) {
+ _clippedBottom = y;
+ }
};
/**
@@ -207,12 +214,14 @@ public:
/**
* Constructor
*/
- SpriteDrawer(byte *data, size_t filesize) : _data(data), _filesize(filesize) {}
+ SpriteDrawer(byte *data, size_t filesize) : _data(data), _filesize(filesize) {
+ }
/**
* Destructor
*/
- virtual ~SpriteDrawer() {}
+ virtual ~SpriteDrawer() {
+ }
/**
* Draw a sprite frame based on a passed offset into the data stream
@@ -325,5 +334,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* MADS_SPRITES_H */
+#endif
diff --git a/engines/xeen/subtitles.cpp b/engines/mm/xeen/subtitles.cpp
similarity index 96%
rename from engines/xeen/subtitles.cpp
rename to engines/mm/xeen/subtitles.cpp
index 3fb2a54bd78..91e80ab7fb1 100644
--- a/engines/xeen/subtitles.cpp
+++ b/engines/mm/xeen/subtitles.cpp
@@ -20,11 +20,12 @@
*/
#include "common/scummsys.h"
-#include "xeen/subtitles.h"
-#include "xeen/events.h"
-#include "xeen/files.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/subtitles.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
static const char *SUBTITLE_LINE = "\f35\x3""c\v190\t000%s";
@@ -166,3 +167,4 @@ void Subtitles::show() {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/subtitles.h b/engines/mm/xeen/subtitles.h
similarity index 96%
rename from engines/xeen/subtitles.h
rename to engines/mm/xeen/subtitles.h
index d0a4e9efb66..dd4310b69b3 100644
--- a/engines/xeen/subtitles.h
+++ b/engines/mm/xeen/subtitles.h
@@ -23,8 +23,9 @@
#define XEEN_SUBTITLES_H
#include "common/str-array.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
class Subtitles {
@@ -100,5 +101,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SUBTITLES_H */
+#endif
diff --git a/engines/xeen/swordsofxeen/swordsofxeen.cpp b/engines/mm/xeen/swordsofxeen/swordsofxeen.cpp
similarity index 92%
rename from engines/xeen/swordsofxeen/swordsofxeen.cpp
rename to engines/mm/xeen/swordsofxeen/swordsofxeen.cpp
index 254e0234c8a..df8a662734c 100644
--- a/engines/xeen/swordsofxeen/swordsofxeen.cpp
+++ b/engines/mm/xeen/swordsofxeen/swordsofxeen.cpp
@@ -19,13 +19,14 @@
*
*/
-#include "xeen/swordsofxeen/swordsofxeen.h"
-#include "xeen/swordsofxeen/swordsofxeen_menu.h"
+#include "mm/xeen/swordsofxeen/swordsofxeen.h"
+#include "mm/xeen/swordsofxeen/swordsofxeen_menu.h"
+namespace MM {
namespace Xeen {
namespace SwordsOfXeen {
-SwordsOfXeenEngine::SwordsOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
+SwordsOfXeenEngine::SwordsOfXeenEngine(OSystem *syst, const MightAndMagicGameDescription *gameDesc)
: XeenEngine(syst, gameDesc) {
}
@@ -123,3 +124,4 @@ void SwordsOfXeenEngine::showCutscene(const Common::String &name, int status, ui
} // End of namespace SwordsOfXeen
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/swordsofxeen/swordsofxeen.h b/engines/mm/xeen/swordsofxeen/swordsofxeen.h
similarity index 89%
rename from engines/xeen/swordsofxeen/swordsofxeen.h
rename to engines/mm/xeen/swordsofxeen/swordsofxeen.h
index 68ca07f42c6..51cc5510d02 100644
--- a/engines/xeen/swordsofxeen/swordsofxeen.h
+++ b/engines/mm/xeen/swordsofxeen/swordsofxeen.h
@@ -22,9 +22,10 @@
#ifndef XEEN_SWORDSOFXEEN_SWORDSOFXEEN_H
#define XEEN_SWORDSOFXEEN_SWORDSOFXEEN_H
-#include "xeen/xeen.h"
-#include "xeen/worldofxeen/worldofxeen_cutscenes.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/worldofxeen/worldofxeen_cutscenes.h"
+namespace MM {
namespace Xeen {
namespace SwordsOfXeen {
@@ -57,7 +58,7 @@ protected:
*/
void death() override;
public:
- SwordsOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+ SwordsOfXeenEngine(OSystem *syst, const MightAndMagicGameDescription *gameDesc);
~SwordsOfXeenEngine() override {}
/**
@@ -75,5 +76,6 @@ public:
} // End of namespace SwordsOfXeen
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SWORDSOFXEEN_SWORDSOFXEEN_H */
+#endif
diff --git a/engines/xeen/swordsofxeen/swordsofxeen_menu.cpp b/engines/mm/xeen/swordsofxeen/swordsofxeen_menu.cpp
similarity index 93%
rename from engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
rename to engines/mm/xeen/swordsofxeen/swordsofxeen_menu.cpp
index 1cba6eb88ae..b00442f960a 100644
--- a/engines/xeen/swordsofxeen/swordsofxeen_menu.cpp
+++ b/engines/mm/xeen/swordsofxeen/swordsofxeen_menu.cpp
@@ -19,11 +19,12 @@
*
*/
-#include "xeen/swordsofxeen/swordsofxeen_menu.h"
-#include "xeen/dialogs/credits_screen.h"
-#include "xeen/dialogs/dialogs_difficulty.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/swordsofxeen/swordsofxeen_menu.h"
+#include "mm/xeen/dialogs/credits_screen.h"
+#include "mm/xeen/dialogs/dialogs_difficulty.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
namespace SwordsOfXeen {
@@ -105,3 +106,4 @@ void MainMenu::loadButtons() {
} // End of namespace SwordsOfXeen
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/swordsofxeen/swordsofxeen_menu.h b/engines/mm/xeen/swordsofxeen/swordsofxeen_menu.h
similarity index 94%
rename from engines/xeen/swordsofxeen/swordsofxeen_menu.h
rename to engines/mm/xeen/swordsofxeen/swordsofxeen_menu.h
index 3697ecaa9dd..f8e6057e7b3 100644
--- a/engines/xeen/swordsofxeen/swordsofxeen_menu.h
+++ b/engines/mm/xeen/swordsofxeen/swordsofxeen_menu.h
@@ -22,8 +22,9 @@
#ifndef XEEN_SWORDSOFXEEN_MENU_H
#define XEEN_SWORDSOFXEEN_MENU_H
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/dialogs/dialogs.h"
+namespace MM {
namespace Xeen {
namespace SwordsOfXeen {
@@ -55,5 +56,6 @@ public:
} // End of namespace SwordsOfXeen
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_SWORDSOFXEEN_MENU_H */
+#endif
diff --git a/engines/xeen/window.cpp b/engines/mm/xeen/window.cpp
similarity index 95%
rename from engines/xeen/window.cpp
rename to engines/mm/xeen/window.cpp
index f6f30617135..f9f32588d7e 100644
--- a/engines/xeen/window.cpp
+++ b/engines/mm/xeen/window.cpp
@@ -19,9 +19,10 @@
*
*/
-#include "xeen/window.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/window.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
Windows::Windows() {
@@ -112,21 +113,21 @@ void Windows::windowClosed(Window *win) {
/*------------------------------------------------------------------------*/
Window::Window() : FontSurface(), _enabled(false),
- _a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) {
+_a(0), _border(0), _xLo(0), _xHi(0), _ycL(0), _ycH(0) {
}
Window::Window(const Window &src) : FontSurface(), _enabled(src._enabled),
- _a(src._a), _border(src._border), _xLo(src._xLo), _ycL(src._ycL),
- _xHi(src._xHi), _ycH(src._ycH) {
+_a(src._a), _border(src._border), _xLo(src._xLo), _ycL(src._ycL),
+_xHi(src._xHi), _ycH(src._ycH) {
setBounds(src._bounds);
create(*g_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
}
Window::Window(const Common::Rect &bounds, int a, int border,
- int xLo, int ycL, int xHi, int ycH): FontSurface(),
- _enabled(false), _a(a), _border(border),
- _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
+ int xLo, int ycL, int xHi, int ycH) : FontSurface(),
+ _enabled(false), _a(a), _border(border),
+ _xLo(xLo), _ycL(ycL), _xHi(xHi), _ycH(ycH) {
setBounds(bounds);
create(*g_vm->_screen, Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
}
@@ -267,3 +268,4 @@ bool Window::isFullScreen() const {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/window.h b/engines/mm/xeen/window.h
similarity index 90%
rename from engines/xeen/window.h
rename to engines/mm/xeen/window.h
index fee9b22dd98..3e5a28ec408 100644
--- a/engines/xeen/window.h
+++ b/engines/mm/xeen/window.h
@@ -24,9 +24,10 @@
#include "common/rect.h"
#include "common/str.h"
-#include "xeen/font.h"
-#include "xeen/sprites.h"
+#include "mm/xeen/font.h"
+#include "mm/xeen/sprites.h"
+namespace MM {
namespace Xeen {
#define GAME_WINDOW 28
@@ -43,8 +44,10 @@ struct DrawStruct {
int _flags;
DrawStruct(int frame, int x, int y, int scale = 0, int flags = 0) :
- _sprites(nullptr), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {}
- DrawStruct(): _sprites(nullptr), _frame(0), _x(0), _y(0), _scale(0), _flags(0) {}
+ _sprites(nullptr), _frame(frame), _x(x), _y(y), _scale(scale), _flags(flags) {
+ }
+ DrawStruct() : _sprites(nullptr), _frame(0), _x(0), _y(0), _scale(0), _flags(0) {
+ }
};
class Windows : public FontData {
@@ -58,7 +61,9 @@ public:
/**
* Returns a specified window
*/
- Window &operator[](int index) { return _windows[index]; }
+ Window &operator[](int index) {
+ return _windows[index];
+ }
/**
* Close all currently open windows
@@ -76,7 +81,7 @@ public:
void windowClosed(Window *win);
};
-class Window: public FontSurface {
+class Window : public FontSurface {
private:
Common::Rect _bounds;
Common::Rect _innerBounds;
@@ -97,13 +102,16 @@ public:
Window(const Window &src);
Window(const Common::Rect &bounds, int a, int border,
int xLo, int ycL, int xHi, int ycH);
- ~Window() override {}
+ ~Window() override {
+ }
void addDirtyRect(const Common::Rect &r) override;
void setBounds(const Common::Rect &r);
- const Common::Rect &getBounds() { return _bounds; }
+ const Common::Rect &getBounds() {
+ return _bounds;
+ }
void open();
@@ -158,5 +166,6 @@ public:
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_WINDOW_H */
+#endif
diff --git a/engines/xeen/worldofxeen/clouds_cutscenes.cpp b/engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
similarity index 99%
rename from engines/xeen/worldofxeen/clouds_cutscenes.cpp
rename to engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
index 4f1657fd5af..f6fcceeaa50 100644
--- a/engines/xeen/worldofxeen/clouds_cutscenes.cpp
+++ b/engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
@@ -19,9 +19,10 @@
*
*/
-#include "xeen/worldofxeen/clouds_cutscenes.h"
-#include "xeen/sound.h"
+#include "mm/xeen/worldofxeen/clouds_cutscenes.h"
+#include "mm/xeen/sound.h"
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
@@ -1304,3 +1305,4 @@ const byte CloudsCutscenes::_DECODE_TABLE2[256] = {
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/worldofxeen/clouds_cutscenes.h b/engines/mm/xeen/worldofxeen/clouds_cutscenes.h
similarity index 94%
rename from engines/xeen/worldofxeen/clouds_cutscenes.h
rename to engines/mm/xeen/worldofxeen/clouds_cutscenes.h
index c110ba49608..2c30f4091c6 100644
--- a/engines/xeen/worldofxeen/clouds_cutscenes.h
+++ b/engines/mm/xeen/worldofxeen/clouds_cutscenes.h
@@ -22,10 +22,11 @@
#ifndef XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H
#define XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H
-#include "xeen/cutscenes.h"
-#include "xeen/subtitles.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/cutscenes.h"
+#include "mm/xeen/subtitles.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
@@ -95,5 +96,6 @@ public:
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_WORLDOFXEEN_CLOUDS_CUTSCENES_H */
+#endif
diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp
similarity index 99%
rename from engines/xeen/worldofxeen/darkside_cutscenes.cpp
rename to engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp
index 634fbf58edf..f97449915c8 100644
--- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp
+++ b/engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp
@@ -19,15 +19,16 @@
*
*/
-#include "xeen/sound.h"
-#include "xeen/xeen.h"
-#include "xeen/worldofxeen/darkside_cutscenes.h"
-#include "xeen/worldofxeen/worldofxeen.h"
+#include "mm/xeen/sound.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/worldofxeen/darkside_cutscenes.h"
+#include "mm/xeen/worldofxeen/worldofxeen.h"
#define WAIT(TIME) if (_subtitles.wait(TIME)) return false
+namespace MM {
namespace Xeen {
- namespace WorldOfXeen {
+namespace WorldOfXeen {
#define WAIT_SUBTITLES(time) \
_subtitles.show(); \
@@ -1758,3 +1759,4 @@ bool DarkSideCutscenes::showPharaohEndTextInner(const char *msg1, const char *ms
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.h b/engines/mm/xeen/worldofxeen/darkside_cutscenes.h
similarity index 97%
rename from engines/xeen/worldofxeen/darkside_cutscenes.h
rename to engines/mm/xeen/worldofxeen/darkside_cutscenes.h
index 738e3a8816f..196ee8a449a 100644
--- a/engines/xeen/worldofxeen/darkside_cutscenes.h
+++ b/engines/mm/xeen/worldofxeen/darkside_cutscenes.h
@@ -22,8 +22,9 @@
#ifndef XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H
#define XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H
-#include "xeen/cutscenes.h"
+#include "mm/xeen/cutscenes.h"
+namespace MM {
namespace Xeen {
class XeenEngine;
@@ -125,5 +126,6 @@ public:
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_WORLDOFXEEN_DARKSIDE_CUTSCENES_H */
+#endif
diff --git a/engines/xeen/worldofxeen/worldofxeen.cpp b/engines/mm/xeen/worldofxeen/worldofxeen.cpp
similarity index 93%
rename from engines/xeen/worldofxeen/worldofxeen.cpp
rename to engines/mm/xeen/worldofxeen/worldofxeen.cpp
index 4a2af5738b8..d6be73fbfc2 100644
--- a/engines/xeen/worldofxeen/worldofxeen.cpp
+++ b/engines/mm/xeen/worldofxeen/worldofxeen.cpp
@@ -19,17 +19,18 @@
*
*/
-#include "xeen/worldofxeen/worldofxeen.h"
-#include "xeen/worldofxeen/darkside_cutscenes.h"
-#include "xeen/worldofxeen/clouds_cutscenes.h"
-#include "xeen/worldofxeen/worldofxeen_menu.h"
-#include "xeen/sound.h"
+#include "mm/xeen/worldofxeen/worldofxeen.h"
+#include "mm/xeen/worldofxeen/darkside_cutscenes.h"
+#include "mm/xeen/worldofxeen/clouds_cutscenes.h"
+#include "mm/xeen/worldofxeen/worldofxeen_menu.h"
+#include "mm/xeen/sound.h"
#include "common/config-manager.h"
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
-WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
+WorldOfXeenEngine::WorldOfXeenEngine(OSystem *syst, const MightAndMagicGameDescription *gameDesc)
: XeenEngine(syst, gameDesc), WorldOfXeenCutscenes(this) {
}
@@ -197,3 +198,4 @@ void WorldOfXeenEngine::showMainMenu() {
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/worldofxeen/worldofxeen.h b/engines/mm/xeen/worldofxeen/worldofxeen.h
similarity index 85%
rename from engines/xeen/worldofxeen/worldofxeen.h
rename to engines/mm/xeen/worldofxeen/worldofxeen.h
index 8ee8c8009c5..9d22ab1a78e 100644
--- a/engines/xeen/worldofxeen/worldofxeen.h
+++ b/engines/mm/xeen/worldofxeen/worldofxeen.h
@@ -22,9 +22,10 @@
#ifndef XEEN_WORLDOFXEEN_WORLDOFXEEN_H
#define XEEN_WORLDOFXEEN_WORLDOFXEEN_H
-#include "xeen/xeen.h"
-#include "xeen/worldofxeen/worldofxeen_cutscenes.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/worldofxeen/worldofxeen_cutscenes.h"
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
@@ -50,7 +51,7 @@ protected:
*/
void death() override;
public:
- WorldOfXeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+ WorldOfXeenEngine(OSystem *syst, const MightAndMagicGameDescription *gameDesc);
~WorldOfXeenEngine() override {}
/**
@@ -64,9 +65,10 @@ public:
void dream() override;
};
-#define WOX_VM (*(::Xeen::WorldOfXeen::WorldOfXeenEngine *)g_vm)
+#define WOX_VM (*(::MM::Xeen::WorldOfXeen::WorldOfXeenEngine *)g_vm)
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_WORLDOFXEEN_WORLDOFXEEN_H */
+#endif
diff --git a/engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp b/engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.cpp
similarity index 99%
rename from engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp
rename to engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.cpp
index 9119d51d247..363a640ec64 100644
--- a/engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp
+++ b/engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.cpp
@@ -19,12 +19,13 @@
*
*/
-#include "xeen/worldofxeen/worldofxeen_cutscenes.h"
-#include "xeen/sound.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/worldofxeen/worldofxeen_cutscenes.h"
+#include "mm/xeen/sound.h"
+#include "mm/xeen/xeen.h"
#define WAIT(TIME) if (_subtitles.wait(TIME)) return false
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
@@ -695,3 +696,4 @@ void WorldOfXeenCutscenes::setSubtitle2(const Common::String &msg) {
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/worldofxeen/worldofxeen_cutscenes.h b/engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.h
similarity index 92%
rename from engines/xeen/worldofxeen/worldofxeen_cutscenes.h
rename to engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.h
index 42472c1fea1..75680373a8e 100644
--- a/engines/xeen/worldofxeen/worldofxeen_cutscenes.h
+++ b/engines/mm/xeen/worldofxeen/worldofxeen_cutscenes.h
@@ -22,10 +22,11 @@
#ifndef XEEN_WORLDOFXEEN_WORLDOFXEEN_CUTSCENES_H
#define XEEN_WORLDOFXEEN_WORLDOFXEEN_CUTSCENES_H
-#include "xeen/worldofxeen/clouds_cutscenes.h"
-#include "xeen/worldofxeen/darkside_cutscenes.h"
-#include "xeen/xeen.h"
+#include "mm/xeen/worldofxeen/clouds_cutscenes.h"
+#include "mm/xeen/worldofxeen/darkside_cutscenes.h"
+#include "mm/xeen/xeen.h"
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
@@ -80,5 +81,6 @@ public:
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_WORLDOFXEEN_WORLDOFXEEN_CUTSCENES_H */
+#endif
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/mm/xeen/worldofxeen/worldofxeen_menu.cpp
similarity index 98%
rename from engines/xeen/worldofxeen/worldofxeen_menu.cpp
rename to engines/mm/xeen/worldofxeen/worldofxeen_menu.cpp
index 1b2223838b8..9bc30ba10c3 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/mm/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -20,12 +20,13 @@
*/
#include "common/scummsys.h"
-#include "xeen/worldofxeen/worldofxeen_menu.h"
-#include "xeen/worldofxeen/worldofxeen.h"
-#include "xeen/dialogs/credits_screen.h"
-#include "xeen/dialogs/dialogs_difficulty.h"
-#include "xeen/resources.h"
+#include "mm/xeen/worldofxeen/worldofxeen_menu.h"
+#include "mm/xeen/worldofxeen/worldofxeen.h"
+#include "mm/xeen/dialogs/credits_screen.h"
+#include "mm/xeen/dialogs/dialogs_difficulty.h"
+#include "mm/xeen/resources.h"
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
@@ -639,3 +640,4 @@ bool OtherOptionsDialog::handleEvents() {
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.h b/engines/mm/xeen/worldofxeen/worldofxeen_menu.h
similarity index 98%
rename from engines/xeen/worldofxeen/worldofxeen_menu.h
rename to engines/mm/xeen/worldofxeen/worldofxeen_menu.h
index 3c0853f49fa..2764a008bc8 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.h
+++ b/engines/mm/xeen/worldofxeen/worldofxeen_menu.h
@@ -22,10 +22,11 @@
#ifndef XEEN_WORLDOFXEEN_WORLDOFXEEN_MENU_H
#define XEEN_WORLDOFXEEN_WORLDOFXEEN_MENU_H
-#include "xeen/xeen.h"
-#include "xeen/dialogs/dialogs.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/dialogs/dialogs.h"
#include "common/array.h"
+namespace MM {
namespace Xeen {
namespace WorldOfXeen {
@@ -317,5 +318,6 @@ public:
} // End of namespace WorldOfXeen
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_WORLDOFXEEN_WORLDOFXEEN_MENU_H */
+#endif
diff --git a/engines/xeen/xeen.cpp b/engines/mm/xeen/xeen.cpp
similarity index 96%
rename from engines/xeen/xeen.cpp
rename to engines/mm/xeen/xeen.cpp
index a3e9e86643e..76dc3d5c94b 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/mm/xeen/xeen.cpp
@@ -24,16 +24,17 @@
#include "common/debug-channels.h"
#include "common/events.h"
#include "engines/util.h"
-#include "xeen/xeen.h"
-#include "xeen/files.h"
-#include "xeen/resources.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/resources.h"
+namespace MM {
namespace Xeen {
XeenEngine *g_vm = nullptr;
-XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
- : Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") {
+XeenEngine::XeenEngine(OSystem *syst, const MightAndMagicGameDescription *gameDesc)
+ : Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") {
_combat = nullptr;
_debugger = nullptr;
@@ -234,7 +235,7 @@ void XeenEngine::play() {
_interface->startup();
if (_mode == MODE_STARTUP) {
-// _screen->fadeOut();
+ // _screen->fadeOut();
}
(*_windows)[0].update();
@@ -327,3 +328,4 @@ void XeenEngine::GUIError(const Common::U32String &msg) {
}
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/xeen.h b/engines/mm/xeen/xeen.h
similarity index 85%
rename from engines/xeen/xeen.h
rename to engines/mm/xeen/xeen.h
index ae72d1b6ef4..f15a1da2300 100644
--- a/engines/xeen/xeen.h
+++ b/engines/mm/xeen/xeen.h
@@ -29,45 +29,38 @@
#include "common/serializer.h"
#include "common/util.h"
#include "engines/engine.h"
-#include "xeen/combat.h"
-#include "xeen/debugger.h"
-#include "xeen/dialogs/dialogs.h"
-#include "xeen/events.h"
-#include "xeen/files.h"
-#include "xeen/interface.h"
-#include "xeen/locations.h"
-#include "xeen/map.h"
-#include "xeen/party.h"
-#include "xeen/patcher.h"
-#include "xeen/resources.h"
-#include "xeen/saves.h"
-#include "xeen/screen.h"
-#include "xeen/scripts.h"
-#include "xeen/sound.h"
-#include "xeen/spells.h"
-#include "xeen/window.h"
-#include "xeen/detection.h"
+#include "mm/xeen/combat.h"
+#include "mm/xeen/debugger.h"
+#include "mm/xeen/dialogs/dialogs.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/files.h"
+#include "mm/xeen/interface.h"
+#include "mm/xeen/locations.h"
+#include "mm/xeen/map.h"
+#include "mm/xeen/party.h"
+#include "mm/xeen/patcher.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/saves.h"
+#include "mm/xeen/screen.h"
+#include "mm/xeen/scripts.h"
+#include "mm/xeen/sound.h"
+#include "mm/xeen/spells.h"
+#include "mm/xeen/window.h"
+#include "mm/detection.h"
+#include "mm/mm.h"
/**
* This is the namespace of the Xeen engine.
*
- * Status of this engine: In Development
- *
* Games using this engine:
* - Might & Magic 4: Clouds of Xeen
* - Might & Magic 5: Darkside of Xeen
* - Might & Magic: World of Xeen
* - Might & Magic: Swords of Xeen
*/
+namespace MM {
namespace Xeen {
-enum XeenDebugChannels {
- kDebugPath = 1 << 0,
- kDebugScripts = 1 << 1,
- kDebugGraphics = 1 << 2,
- kDebugSound = 1 << 3
-};
-
enum Mode {
MODE_FF = -1,
MODE_STARTUP = 0,
@@ -105,10 +98,11 @@ class XeenEngine : public Engine {
bool _showItemCosts;
bool _durableArmor;
- ExtendedOptions() : _showItemCosts(false), _durableArmor(false) {}
+ ExtendedOptions() : _showItemCosts(false), _durableArmor(false) {
+ }
};
private:
- const XeenGameDescription *_gameDescription;
+ const MightAndMagicGameDescription *_gameDescription;
Common::RandomSource _randomSource;
private:
/**
@@ -188,7 +182,7 @@ public:
uint _finalScore;
ExtendedOptions _extOptions;
public:
- XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
+ XeenEngine(OSystem *syst, const MM::MightAndMagicGameDescription *gameDesc);
~XeenEngine() override;
/**
@@ -240,12 +234,16 @@ public:
/**
* Returns true if the game should be exited (either quitting, exiting to the main menu, or loading a savegame)
*/
- bool shouldExit() const { return _gameMode != GMODE_NONE || isLoadPending() || shouldQuit(); }
+ bool shouldExit() const {
+ return _gameMode != GMODE_NONE || isLoadPending() || shouldQuit();
+ }
/**
* Returns true if a savegame load is pending
*/
- bool isLoadPending() const { return _loadSaveSlot != -1; }
+ bool isLoadPending() const {
+ return _loadSaveSlot != -1;
+ }
/**
* Load a savegame
@@ -283,7 +281,8 @@ public:
* @param status For World of Xeen, Goober status
* @param score Final score
*/
- virtual void showCutscene(const Common::String &name, int status, uint score) {}
+ virtual void showCutscene(const Common::String &name, int status, uint score) {
+ }
/**
* Dream sequence
@@ -310,5 +309,6 @@ public:
extern XeenEngine *g_vm;
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_XEEN_H */
+#endif
diff --git a/engines/xeen/xsurface.cpp b/engines/mm/xeen/xsurface.cpp
similarity index 88%
rename from engines/xeen/xsurface.cpp
rename to engines/mm/xeen/xsurface.cpp
index 5397654520a..b92d5e16a19 100644
--- a/engines/xeen/xsurface.cpp
+++ b/engines/mm/xeen/xsurface.cpp
@@ -21,10 +21,12 @@
#include "common/algorithm.h"
#include "common/util.h"
-#include "xeen/xsurface.h"
-#include "xeen/resources.h"
-#include "xeen/screen.h"
+#include "mm/xeen/xsurface.h"
+#include "mm/xeen/resources.h"
+#include "mm/xeen/screen.h"
+namespace MM {
namespace Xeen {
} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/xeen/xsurface.h b/engines/mm/xeen/xsurface.h
similarity index 80%
rename from engines/xeen/xsurface.h
rename to engines/mm/xeen/xsurface.h
index d1dd695ad55..d4c32403e31 100644
--- a/engines/xeen/xsurface.h
+++ b/engines/mm/xeen/xsurface.h
@@ -27,26 +27,34 @@
#include "common/rect.h"
#include "graphics/managed_surface.h"
+namespace MM {
namespace Xeen {
-class BaseSurface: public Graphics::ManagedSurface {
+class BaseSurface : public Graphics::ManagedSurface {
public:
void addDirtyRect(const Common::Rect &r) override {
Graphics::ManagedSurface::addDirtyRect(r);
}
public:
- BaseSurface() : Graphics::ManagedSurface() {}
- BaseSurface(int width, int height) : Graphics::ManagedSurface(width, height) {}
- ~BaseSurface() override {}
+ BaseSurface() : Graphics::ManagedSurface() {
+ }
+ BaseSurface(int width, int height) : Graphics::ManagedSurface(width, height) {
+ }
+ ~BaseSurface() override {
+ }
};
class XSurface : public BaseSurface {
public:
- XSurface() : BaseSurface() {}
- XSurface(int width, int height) : BaseSurface(width, height) {}
- ~XSurface() override {}
+ XSurface() : BaseSurface() {
+ }
+ XSurface(int width, int height) : BaseSurface(width, height) {
+ }
+ ~XSurface() override {
+ }
};
} // End of namespace Xeen
+} // End of namespace MM
-#endif /* XEEN_XSURFACE_H */
+#endif
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
deleted file mode 100644
index 71afe7762d2..00000000000
--- a/engines/xeen/module.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-MODULE := engines/xeen
-
-MODULE_OBJS := \
- worldofxeen/clouds_cutscenes.o \
- worldofxeen/darkside_cutscenes.o \
- worldofxeen/worldofxeen_cutscenes.o \
- worldofxeen/worldofxeen_menu.o \
- worldofxeen/worldofxeen.o \
- swordsofxeen/swordsofxeen.o \
- swordsofxeen/swordsofxeen_menu.o \
- dialogs/credits_screen.o \
- dialogs/dialogs.o \
- dialogs/dialogs_awards.o \
- dialogs/dialogs_char_info.o \
- dialogs/dialogs_control_panel.o \
- dialogs/dialogs_copy_protection.o \
- dialogs/dialogs_create_char.o \
- dialogs/dialogs_difficulty.o \
- dialogs/dialogs_dismiss.o \
- dialogs/dialogs_exchange.o \
- dialogs/dialogs_info.o \
- dialogs/dialogs_input.o \
- dialogs/dialogs_items.o \
- dialogs/dialogs_map.o \
- dialogs/dialogs_message.o \
- dialogs/dialogs_party.o \
- dialogs/dialogs_query.o \
- dialogs/dialogs_quests.o \
- dialogs/dialogs_quick_fight.o \
- dialogs/dialogs_quick_ref.o \
- dialogs/dialogs_spells.o \
- dialogs/dialogs_whowill.o \
- dialogs/please_wait.o \
- character.o \
- combat.o \
- cutscenes.o \
- debugger.o \
- events.o \
- files.o \
- font.o \
- interface.o \
- interface_minimap.o \
- interface_scene.o \
- item.o \
- locations.o \
- map.o \
- metaengine.o \
- party.o \
- patcher.o \
- resources.o \
- saves.o \
- screen.o \
- scripts.o \
- sound.o \
- sound_driver.o \
- sound_driver_adlib.o \
- spells.o \
- sprites.o \
- subtitles.o \
- window.o \
- xeen.o \
- xsurface.o
-
-# This module can be built as a plugin
-ifeq ($(ENABLE_XEEN), DYNAMIC_PLUGIN)
-PLUGIN := 1
-endif
-
-# Include common rules
-include $(srcdir)/rules.mk
-
-# Detection objects
-DETECT_OBJS += $(MODULE)/detection.o
Commit: f24debf602868fb658ef96bbd3aae63db7825238
https://github.com/scummvm/scummvm/commit/f24debf602868fb658ef96bbd3aae63db7825238
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:40+01:00
Commit Message:
MM: MM1: Skeleton engine class
Changed paths:
A engines/mm/mm1/mm1.cpp
A engines/mm/mm1/mm1.h
A engines/mm/mm1/ui_element.cpp
A engines/mm/mm1/ui_element.h
engines/mm/detection_tables.h
engines/mm/metaengine.cpp
engines/mm/module.mk
diff --git a/engines/mm/detection_tables.h b/engines/mm/detection_tables.h
index afaa96f8e33..43192b4c28e 100644
--- a/engines/mm/detection_tables.h
+++ b/engines/mm/detection_tables.h
@@ -22,6 +22,22 @@
namespace MM {
static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
+ {
+ // Might and Magic 1
+ {
+ "mm1",
+ nullptr,
+ AD_ENTRY1s("wallpix.dta", "86a7ef03fd5bf434d83012b07fa92680", 123059),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ GType_MightAndMagic1,
+ 0
+ },
+
+
{
// World of Xeen
{
diff --git a/engines/mm/metaengine.cpp b/engines/mm/metaengine.cpp
index cb6f599f258..c9e39850fff 100644
--- a/engines/mm/metaengine.cpp
+++ b/engines/mm/metaengine.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "mm/mm1/mm1.h"
#include "mm/xeen/xeen.h"
#include "mm/xeen/worldofxeen/worldofxeen.h"
#include "mm/xeen/swordsofxeen/swordsofxeen.h"
@@ -107,6 +108,9 @@ Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const
const MM::MightAndMagicGameDescription *gd = (const MM::MightAndMagicGameDescription *)desc;
switch (gd->gameID) {
+ case MM::GType_MightAndMagic1:
+ *engine = new MM::MM1::MM1Engine(syst, gd);
+ break;
case MM::GType_Clouds:
case MM::GType_DarkSide:
case MM::GType_WorldOfXeen:
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
new file mode 100644
index 00000000000..0b2a30a34b3
--- /dev/null
+++ b/engines/mm/mm1/mm1.cpp
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "engines/util.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+
+MM1Engine *g_engine = nullptr;
+
+MM1Engine::MM1Engine(OSystem *syst, const MightAndMagicGameDescription *gameDesc)
+ : Engine(syst), _gameDescription(gameDesc), _randomSource("MM1") {
+ g_engine = this;
+}
+
+MM1Engine::~MM1Engine() {
+ g_engine = nullptr;
+}
+
+Common::Error MM1Engine::run() {
+ return Common::kNoError;
+}
+
+} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
new file mode 100644
index 00000000000..98200c19e3b
--- /dev/null
+++ b/engines/mm/mm1/mm1.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MM1_H
+#define MM1_MM1_H
+
+#include "common/random.h"
+#include "mm/detection.h"
+#include "mm/mm.h"
+
+/**
+ * This is the Might and Magic I engine
+ */
+namespace MM {
+namespace MM1 {
+
+class MM1Engine : public Engine {
+private:
+ const MightAndMagicGameDescription *_gameDescription;
+ Common::RandomSource _randomSource;
+private:
+ // Engine APIs
+ Common::Error run() override;
+
+public:
+ MM1Engine(OSystem *syst, const MightAndMagicGameDescription *gameDesc);
+ ~MM1Engine() override;
+
+ /**
+ * Returns a random number
+ */
+ int getRandomNumber(int minNumber, int maxNumber) {
+ return _randomSource.getRandomNumber(maxNumber - minNumber + 1) + minNumber;
+ }
+};
+
+extern MM1Engine *g_engine;
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/ui_element.cpp b/engines/mm/mm1/ui_element.cpp
new file mode 100644
index 00000000000..9dc92f31ad7
--- /dev/null
+++ b/engines/mm/mm1/ui_element.cpp
@@ -0,0 +1,28 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/ui_element.h"
+
+namespace MM {
+namespace MM1 {
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/ui_element.h b/engines/mm/mm1/ui_element.h
new file mode 100644
index 00000000000..e7c3ee87d6e
--- /dev/null
+++ b/engines/mm/mm1/ui_element.h
@@ -0,0 +1,32 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_UI_ELEMENT_H
+#define MM1_UI_ELEMENT_H
+
+namespace MM {
+namespace MM1 {
+
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index e03b9fb3454..75df361fc76 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -2,6 +2,8 @@ MODULE := engines/mm
MODULE_OBJS := \
metaengine.o \
+ mm1/mm1.o \
+ mm1/ui_element.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
xeen/worldofxeen/worldofxeen_cutscenes.o \
Commit: 6fedafac5450896464b7cd892931b6740ba3c8fe
https://github.com/scummvm/scummvm/commit/6fedafac5450896464b7cd892931b6740ba3c8fe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:40+01:00
Commit Message:
MM: MM1: Beginnings of events/ui manager
Changed paths:
A engines/mm/mm1/events.cpp
A engines/mm/mm1/events.h
R engines/mm/mm1/ui_element.cpp
R engines/mm/mm1/ui_element.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/mm1.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
new file mode 100644
index 00000000000..20962bd4238
--- /dev/null
+++ b/engines/mm/mm1/events.cpp
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+#include "graphics/screen.h"
+#include "mm/mm1/events.h"
+
+namespace MM {
+namespace MM1 {
+
+#define FRAME_RATE 20
+#define FRAME_DELAY (1000 / FRAME_RATE)
+
+void Events::runGame() {
+ uint currTime, nextFrameTime = 0;
+ _screen = new Graphics::Screen();
+
+ Common::Event e;
+ for (;;) {
+ while (g_system->getEventManager()->pollEvent(e)) {
+ if (e.type == Common::EVENT_QUIT)
+ return;
+ else
+ processEvent(e);
+ }
+
+ g_system->delayMillis(10);
+ if ((currTime = g_system->getMillis()) >= nextFrameTime) {
+ nextFrameTime = currTime + FRAME_DELAY;
+ tick();
+ }
+ }
+
+ delete _screen;
+}
+
+void Events::processEvent(Common::Event &ev) {
+ switch (ev.type) {
+ case Common::EVENT_KEYDOWN:
+ keypressEvent(ev);
+ break;
+ default:
+ break;
+ }
+}
+
+UIElement::UIElement(UIElement *uiParent) : _parent(uiParent) {
+ if (_parent)
+ _parent->_children.push_back(this);
+}
+
+bool UIElement::tick() {
+ for (size_t i = 0; i < _children.size(); ++i) {
+ if (_children[i]->tick())
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/ui_element.h b/engines/mm/mm1/events.h
similarity index 50%
rename from engines/mm/mm1/ui_element.h
rename to engines/mm/mm1/events.h
index e7c3ee87d6e..a0aad834730 100644
--- a/engines/mm/mm1/ui_element.h
+++ b/engines/mm/mm1/events.h
@@ -19,12 +19,65 @@
*
*/
-#ifndef MM1_UI_ELEMENT_H
-#define MM1_UI_ELEMENT_H
+#ifndef MM1_EVENTS_H
+#define MM1_EVENTS_H
+
+#include "common/array.h"
+#include "common/events.h"
+#include "graphics/screen.h"
namespace MM {
namespace MM1 {
+class UIElement {
+protected:
+ UIElement *_parent;
+ Common::Array<UIElement *> _children;
+public:
+ UIElement(UIElement *uiParent = nullptr);
+ virtual ~UIElement() {}
+
+ /**
+ * Returns the game view
+ */
+ virtual Graphics::Screen *getScreen() const {
+ return _parent ? _parent->getScreen() : nullptr;
+ }
+
+ /**
+ * Called for game frame ticks
+ */
+ virtual bool tick();
+
+ /**
+ * Handles a keypress
+ */
+ virtual bool keypressEvent(const Common::Event &e) {
+ return false;
+ }
+};
+
+class Events : public UIElement {
+private:
+ Graphics::Screen *_screen = nullptr;
+protected:
+ /**
+ * Process an event
+ */
+ void processEvent(Common::Event &ev);
+public:
+ Events() {}
+ virtual ~Events() {}
+
+ /**
+ * Main game loop
+ */
+ void runGame();
+
+ Graphics::Screen *getScreen() const override {
+ return _screen;
+ }
+};
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 0b2a30a34b3..921047cde17 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -41,6 +41,9 @@ MM1Engine::~MM1Engine() {
}
Common::Error MM1Engine::run() {
+ initGraphics(320, 200);
+
+ runGame();
return Common::kNoError;
}
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index 98200c19e3b..af1455d54e0 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -25,6 +25,7 @@
#include "common/random.h"
#include "mm/detection.h"
#include "mm/mm.h"
+#include "mm/mm1/events.h"
/**
* This is the Might and Magic I engine
@@ -32,7 +33,7 @@
namespace MM {
namespace MM1 {
-class MM1Engine : public Engine {
+class MM1Engine : public Engine, public Events {
private:
const MightAndMagicGameDescription *_gameDescription;
Common::RandomSource _randomSource;
diff --git a/engines/mm/mm1/ui_element.cpp b/engines/mm/mm1/ui_element.cpp
deleted file mode 100644
index 9dc92f31ad7..00000000000
--- a/engines/mm/mm1/ui_element.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "mm/mm1/ui_element.h"
-
-namespace MM {
-namespace MM1 {
-
-} // namespace MM1
-} // namespace MM
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 75df361fc76..ba032aa7f41 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -2,8 +2,8 @@ MODULE := engines/mm
MODULE_OBJS := \
metaengine.o \
+ mm1/events.o \
mm1/mm1.o \
- mm1/ui_element.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
xeen/worldofxeen/worldofxeen_cutscenes.o \
Commit: 96fb461abb2f496c2726ca3cd86d4473b3733c9a
https://github.com/scummvm/scummvm/commit/96fb461abb2f496c2726ca3cd86d4473b3733c9a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:40+01:00
Commit Message:
MM: MM1: Beginnings of screen viewer
Changed paths:
A engines/mm/mm1/gfx.cpp
A engines/mm/mm1/gfx.h
A engines/mm/mm1/views/screen_view.cpp
A engines/mm/mm1/views/screen_view.h
A engines/mm/mm1/views/text_view.cpp
A engines/mm/mm1/views/text_view.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/mm1.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 20962bd4238..6db1e601c04 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -46,6 +46,8 @@ void Events::runGame() {
if ((currTime = g_system->getMillis()) >= nextFrameTime) {
nextFrameTime = currTime + FRAME_DELAY;
tick();
+ draw();
+ _screen->update();
}
}
@@ -67,6 +69,11 @@ UIElement::UIElement(UIElement *uiParent) : _parent(uiParent) {
_parent->_children.push_back(this);
}
+void UIElement::draw() {
+ for (size_t i = 0; i < _children.size(); ++i)
+ _children[i]->draw();
+}
+
bool UIElement::tick() {
for (size_t i = 0; i < _children.size(); ++i) {
if (_children[i]->tick())
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index a0aad834730..eca73f08eb4 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -44,6 +44,11 @@ public:
return _parent ? _parent->getScreen() : nullptr;
}
+ /**
+ * Draws the element
+ */
+ virtual void draw();
+
/**
* Called for game frame ticks
*/
diff --git a/engines/mm/mm1/gfx.cpp b/engines/mm/mm1/gfx.cpp
new file mode 100644
index 00000000000..4c29a602760
--- /dev/null
+++ b/engines/mm/mm1/gfx.cpp
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+#include "graphics/palette.h"
+#include "mm/mm1/gfx.h"
+
+namespace MM {
+namespace MM1 {
+
+#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
+
+static const byte EGA_PALETTE[64][3] = {
+ {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
+ {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
+ {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
+ {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
+ {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
+ {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
+ {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
+ {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
+};
+
+void GFX::setEgaPalette(int palNum) {
+ byte pal[16 * 3];
+ byte *pDest = pal;
+ const byte *pSrc = &EGA_PALETTE[palNum * 16][0];
+
+ for (int i = 0; i < 16 * 3; ++i, ++pSrc, ++pDest)
+ *pDest = VGA_COLOR_TRANS(*pSrc);
+
+ g_system->getPaletteManager()->setPalette(pal, 0, 16);
+}
+
+} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/mm/mm1/gfx.h b/engines/mm/mm1/gfx.h
new file mode 100644
index 00000000000..e82126a0ccd
--- /dev/null
+++ b/engines/mm/mm1/gfx.h
@@ -0,0 +1,38 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GFX_H
+#define MM1_GFX_H
+
+#include "graphics/palette.h"
+
+namespace MM {
+namespace MM1 {
+
+class GFX {
+public:
+ static void setEgaPalette(int palNum);
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 921047cde17..2718166fe5b 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -25,6 +25,8 @@
#include "common/events.h"
#include "engines/util.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/gfx.h"
+#include "mm/mm1/views/screen_view.h"
namespace MM {
namespace MM1 {
@@ -42,6 +44,8 @@ MM1Engine::~MM1Engine() {
Common::Error MM1Engine::run() {
initGraphics(320, 200);
+ GFX::setEgaPalette(0);
+ Views::ScreenView screenView(this);
runGame();
return Common::kNoError;
diff --git a/engines/mm/mm1/views/screen_view.cpp b/engines/mm/mm1/views/screen_view.cpp
new file mode 100644
index 00000000000..62f817c63c6
--- /dev/null
+++ b/engines/mm/mm1/views/screen_view.cpp
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "mm/mm1/views/screen_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+#define IMAGE_SIZE 16000
+
+void ScreenView::loadScreen(int screenNum) {
+ byte bytes[IMAGE_SIZE];
+ byte v;
+ int len;
+ const byte *srcP;
+ byte *destP = &bytes[0];
+ int index = 0;
+
+ _screenNum = screenNum;
+
+ Common::File f;
+ if (!f.open(Common::String::format("screen%d", screenNum)))
+ error("Could not open screen%d", screenNum);
+ int size = f.readUint16LE();
+
+ // Decompress the image bytes
+ while (size > 0) {
+ v = f.readByte();
+ if (v != 0x7B) {
+ len = 1;
+ --size;
+ } else {
+ len = f.readByte() + 1;
+ v = f.readByte();
+ size -= 3;
+ }
+
+ for (; len > 0; --len) {
+ destP[index] = v;
+
+ index += 80;
+ if (index >= IMAGE_SIZE) {
+ index = 0;
+ ++destP;
+ }
+ }
+ }
+
+ // Create surface from splitting up the nibbles
+ _surface.create(320, 200);
+ srcP = &bytes[0];
+ destP = (byte *)_surface.getPixels();
+
+ for (size_t i = 0; i < IMAGE_SIZE; ++i, ++srcP) {
+ *destP++ = *srcP & 0xf;
+ *destP++ = *srcP >> 4;
+ }
+}
+
+void ScreenView::draw() {
+ if (_surface.empty())
+ loadScreen(0);
+
+ getScreen()->blitFrom(_surface);
+}
+
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/screen_view.h b/engines/mm/mm1/views/screen_view.h
new file mode 100644
index 00000000000..85a0869585c
--- /dev/null
+++ b/engines/mm/mm1/views/screen_view.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SCREEN_VIEW_H
+#define MM1_VIEWS_SCREEN_VIEW_H
+
+#include "mm/mm1/events.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class ScreenView : public UIElement {
+private:
+ Graphics::ManagedSurface _surface;
+protected:
+ int _screenNum;
+
+ void loadScreen(int screenNum);
+public:
+ ScreenView(UIElement *uiParent = nullptr) :
+ UIElement(uiParent), _screenNum(0) {}
+ virtual ~ScreenView() {}
+
+ void draw() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
new file mode 100644
index 00000000000..f9b60be0092
--- /dev/null
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -0,0 +1,30 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
new file mode 100644
index 00000000000..f10b4427cea
--- /dev/null
+++ b/engines/mm/mm1/views/text_view.h
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_TEXT_VIEW_H
+#define MM1_VIEWS_TEXT_VIEW_H
+
+#include "mm/mm1/events.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class TextView : public UIElement {
+public:
+ TextView(UIElement *uiParent = nullptr) :
+ UIElement(uiParent) {}
+ virtual ~TextView() {}
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index ba032aa7f41..e94b335ee38 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -3,7 +3,10 @@ MODULE := engines/mm
MODULE_OBJS := \
metaengine.o \
mm1/events.o \
+ mm1/gfx.o \
mm1/mm1.o \
+ mm1/views/screen_view.o \
+ mm1/views/text_view.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
xeen/worldofxeen/worldofxeen_cutscenes.o \
Commit: 49d5aad064349d5cf2b132664002b9826a43320a
https://github.com/scummvm/scummvm/commit/49d5aad064349d5cf2b132664002b9826a43320a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:40+01:00
Commit Message:
MM: MM1: Fixed screen decoding
Changed paths:
engines/mm/mm1/views/screen_view.cpp
diff --git a/engines/mm/mm1/views/screen_view.cpp b/engines/mm/mm1/views/screen_view.cpp
index 62f817c63c6..af111541cc2 100644
--- a/engines/mm/mm1/views/screen_view.cpp
+++ b/engines/mm/mm1/views/screen_view.cpp
@@ -72,8 +72,9 @@ void ScreenView::loadScreen(int screenNum) {
destP = (byte *)_surface.getPixels();
for (size_t i = 0; i < IMAGE_SIZE; ++i, ++srcP) {
- *destP++ = *srcP & 0xf;
- *destP++ = *srcP >> 4;
+ v = *srcP;
+ for (int j = 0; j < 4; ++j, v <<= 2)
+ *destP++ = v >> 6;
}
}
Commit: 1aaf783fc7e7e861daab1c5dc777c18a2ff074d4
https://github.com/scummvm/scummvm/commit/1aaf783fc7e7e861daab1c5dc777c18a2ff074d4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: MM1: Shifted screen decoder into a new ImageDecoder class
Changed paths:
A engines/mm/mm1/gfx/gfx.cpp
A engines/mm/mm1/gfx/gfx.h
A engines/mm/mm1/gfx/screen_decoder.cpp
A engines/mm/mm1/gfx/screen_decoder.h
A engines/mm/mm1/views/title_view.cpp
A engines/mm/mm1/views/title_view.h
R engines/mm/mm1/gfx.cpp
R engines/mm/mm1/gfx.h
R engines/mm/mm1/views/screen_view.cpp
R engines/mm/mm1/views/screen_view.h
engines/mm/mm1/mm1.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/gfx.cpp b/engines/mm/mm1/gfx/gfx.cpp
similarity index 96%
rename from engines/mm/mm1/gfx.cpp
rename to engines/mm/mm1/gfx/gfx.cpp
index 4c29a602760..489e22a1419 100644
--- a/engines/mm/mm1/gfx.cpp
+++ b/engines/mm/mm1/gfx/gfx.cpp
@@ -21,10 +21,11 @@
#include "common/system.h"
#include "graphics/palette.h"
-#include "mm/mm1/gfx.h"
+#include "mm/mm1/gfx/gfx.h"
namespace MM {
namespace MM1 {
+namespace Gfx {
#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
@@ -50,5 +51,6 @@ void GFX::setEgaPalette(int palNum) {
g_system->getPaletteManager()->setPalette(pal, 0, 16);
}
-} // End of namespace Xeen
-} // End of namespace MM
+} // namespace Gfx
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/gfx.h b/engines/mm/mm1/gfx/gfx.h
similarity index 96%
rename from engines/mm/mm1/gfx.h
rename to engines/mm/mm1/gfx/gfx.h
index e82126a0ccd..dd677fed924 100644
--- a/engines/mm/mm1/gfx.h
+++ b/engines/mm/mm1/gfx/gfx.h
@@ -26,12 +26,14 @@
namespace MM {
namespace MM1 {
+namespace Gfx {
class GFX {
public:
static void setEgaPalette(int palNum);
};
+} // namespace Gfx
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/screen_view.cpp b/engines/mm/mm1/gfx/screen_decoder.cpp
similarity index 70%
rename from engines/mm/mm1/views/screen_view.cpp
rename to engines/mm/mm1/gfx/screen_decoder.cpp
index af111541cc2..b2d55f5507a 100644
--- a/engines/mm/mm1/views/screen_view.cpp
+++ b/engines/mm/mm1/gfx/screen_decoder.cpp
@@ -20,15 +20,28 @@
*/
#include "common/file.h"
-#include "mm/mm1/views/screen_view.h"
+#include "mm/mm1/gfx/screen_decoder.h"
namespace MM {
namespace MM1 {
-namespace Views {
+namespace Gfx {
#define IMAGE_SIZE 16000
-void ScreenView::loadScreen(int screenNum) {
+ScreenDecoder::~ScreenDecoder() {
+ destroy();
+}
+
+void ScreenDecoder::destroy() {
+ _surface.free();
+}
+
+bool ScreenDecoder::loadFile(const Common::String &fname) {
+ Common::File f;
+ return f.open(fname) && loadStream(f);
+}
+
+bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream) {
byte bytes[IMAGE_SIZE];
byte v;
int len;
@@ -36,22 +49,19 @@ void ScreenView::loadScreen(int screenNum) {
byte *destP = &bytes[0];
int index = 0;
- _screenNum = screenNum;
-
- Common::File f;
- if (!f.open(Common::String::format("screen%d", screenNum)))
- error("Could not open screen%d", screenNum);
- int size = f.readUint16LE();
+ int size = stream.readUint16LE();
+ if (size < 0 || size > stream.size())
+ return false;
// Decompress the image bytes
while (size > 0) {
- v = f.readByte();
+ v = stream.readByte();
if (v != 0x7B) {
len = 1;
--size;
} else {
- len = f.readByte() + 1;
- v = f.readByte();
+ len = stream.readByte() + 1;
+ v = stream.readByte();
size -= 3;
}
@@ -67,7 +77,7 @@ void ScreenView::loadScreen(int screenNum) {
}
// Create surface from splitting up the nibbles
- _surface.create(320, 200);
+ _surface.create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
srcP = &bytes[0];
destP = (byte *)_surface.getPixels();
@@ -76,16 +86,10 @@ void ScreenView::loadScreen(int screenNum) {
for (int j = 0; j < 4; ++j, v <<= 2)
*destP++ = v >> 6;
}
-}
-
-void ScreenView::draw() {
- if (_surface.empty())
- loadScreen(0);
- getScreen()->blitFrom(_surface);
+ return true;
}
-
-} // namespace Views
-} // namespace MM1
-} // namespace MM
+} // namespace Gfx
+} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
new file mode 100644
index 00000000000..8d375419ad0
--- /dev/null
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GFX_SCREEN_DECODER_H
+#define MM1_GFX_SCREEN_DECODER_H
+
+#include "image/image_decoder.h"
+#include "graphics/managed_surface.h"
+
+namespace MM {
+namespace MM1 {
+namespace Gfx {
+
+class ScreenDecoder : public Image::ImageDecoder {
+private:
+ Graphics::Surface _surface;
+public:
+ ScreenDecoder() {}
+ ~ScreenDecoder() override;
+
+ void destroy() override;
+ bool loadFile(const Common::String &fname);
+ bool loadStream(Common::SeekableReadStream &stream) override;
+ const Graphics::Surface *getSurface() const override {
+ return &_surface;
+ }
+ const byte *getPalette() const override { return nullptr; }
+ uint16 getPaletteColorCount() const override { return 0; }
+ void clear() { _surface.free(); }
+};
+
+} // namespace Gfx
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 2718166fe5b..ff84f30fb64 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -25,8 +25,8 @@
#include "common/events.h"
#include "engines/util.h"
#include "mm/mm1/mm1.h"
-#include "mm/mm1/gfx.h"
-#include "mm/mm1/views/screen_view.h"
+#include "mm/mm1/gfx/gfx.h"
+#include "mm/mm1/views/title_view.h"
namespace MM {
namespace MM1 {
@@ -44,8 +44,8 @@ MM1Engine::~MM1Engine() {
Common::Error MM1Engine::run() {
initGraphics(320, 200);
- GFX::setEgaPalette(0);
- Views::ScreenView screenView(this);
+ Gfx::GFX::setEgaPalette(0);
+ Views::TitleView screenView(this);
runGame();
return Common::kNoError;
diff --git a/engines/mm/mm1/views/title_view.cpp b/engines/mm/mm1/views/title_view.cpp
new file mode 100644
index 00000000000..2f3abf80a3c
--- /dev/null
+++ b/engines/mm/mm1/views/title_view.cpp
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/title_view.h"
+#include "mm/mm1/gfx/screen_decoder.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+TitleView::TitleView(UIElement *uiParent) : UIElement(uiParent) {
+ Gfx::ScreenDecoder decoder;
+ if (decoder.loadFile("screen0")) {
+ _surface.copyFrom(decoder.getSurface());
+ } else {
+ error("Could not load screen0");
+ }
+}
+
+void TitleView::draw() {
+ getScreen()->blitFrom(_surface);
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/screen_view.h b/engines/mm/mm1/views/title_view.h
similarity index 80%
rename from engines/mm/mm1/views/screen_view.h
rename to engines/mm/mm1/views/title_view.h
index 85a0869585c..4b745022b10 100644
--- a/engines/mm/mm1/views/screen_view.h
+++ b/engines/mm/mm1/views/title_view.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MM1_VIEWS_SCREEN_VIEW_H
-#define MM1_VIEWS_SCREEN_VIEW_H
+#ifndef MM1_VIEWS_TITLE_VIEW_H
+#define MM1_VIEWS_TITLE_VIEW_H
#include "mm/mm1/events.h"
@@ -28,17 +28,12 @@ namespace MM {
namespace MM1 {
namespace Views {
-class ScreenView : public UIElement {
+class TitleView : public UIElement {
private:
Graphics::ManagedSurface _surface;
-protected:
- int _screenNum;
-
- void loadScreen(int screenNum);
public:
- ScreenView(UIElement *uiParent = nullptr) :
- UIElement(uiParent), _screenNum(0) {}
- virtual ~ScreenView() {}
+ TitleView(UIElement *uiParent = nullptr);
+ virtual ~TitleView() {}
void draw() override;
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index e94b335ee38..31f0530a69e 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -3,9 +3,10 @@ MODULE := engines/mm
MODULE_OBJS := \
metaengine.o \
mm1/events.o \
- mm1/gfx.o \
mm1/mm1.o \
- mm1/views/screen_view.o \
+ mm1/gfx/gfx.o \
+ mm1/gfx/screen_decoder.o \
+ mm1/views/title_view.o \
mm1/views/text_view.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
Commit: 3aeb06b42ed1f5fad7f4555761bd51f740357036
https://github.com/scummvm/scummvm/commit/3aeb06b42ed1f5fad7f4555761bd51f740357036
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: Creating new combined mm data file for Xeen & MM1
Changed paths:
A devtools/create_mm/create_xeen/cc.cpp
A devtools/create_mm/create_xeen/cc.h
A devtools/create_mm/create_xeen/clouds.cpp
A devtools/create_mm/create_xeen/clouds.h
A devtools/create_mm/create_xeen/constants.cpp
A devtools/create_mm/create_xeen/constants.h
A devtools/create_mm/create_xeen/create_xeen.cpp
A devtools/create_mm/create_xeen/de_constants.h
A devtools/create_mm/create_xeen/en_constants.h
A devtools/create_mm/create_xeen/file.h
A devtools/create_mm/create_xeen/hash-str.h
A devtools/create_mm/create_xeen/hashmap.cpp
A devtools/create_mm/create_xeen/hashmap.h
A devtools/create_mm/create_xeen/map.cpp
A devtools/create_mm/create_xeen/map.h
A devtools/create_mm/create_xeen/memorypool.cpp
A devtools/create_mm/create_xeen/memorypool.h
A devtools/create_mm/create_xeen/module.mk
A devtools/create_mm/create_xeen/ru_constants.h
A devtools/create_mm/create_xeen/str.cpp
A devtools/create_mm/create_xeen/str.h
A devtools/create_mm/create_xeen/swords.cpp
A devtools/create_mm/create_xeen/swords.h
A devtools/create_mm/files/xeen/CONSTANTS_26
A devtools/create_mm/files/xeen/CONSTANTS_4
A devtools/create_mm/files/xeen/CONSTANTS_7
A devtools/create_mm/files/xeen/CONSTKEYS_26
A devtools/create_mm/files/xeen/CONSTKEYS_4
A devtools/create_mm/files/xeen/CONSTKEYS_7
A devtools/create_mm/files/xeen/aazex255.hed
A devtools/create_mm/files/xeen/aazex255.txt
A devtools/create_mm/files/xeen/animinfo.cld
A devtools/create_mm/files/xeen/mae.cld
A devtools/create_mm/files/xeen/mapnames.cld
A devtools/create_mm/files/xeen/mazex255.dat
A devtools/create_mm/files/xeen/mazex255.evt
A devtools/create_mm/files/xeen/mazex255.mob
A devtools/create_mm/files/xeen/monsters.cld
A devtools/create_mm/files/xeen/monsters.swd
A devtools/create_mm/files/xeen/spells.cld
A devtools/create_mm/files/xeen/version.txt
A devtools/create_mm/files/xeen/wallpics.cld
A devtools/create_mm/files/xeen/xeenmirr.ext
A devtools/create_mm/files/xeen/xeenmirr.txt
A devtools/create_mm/files/xeen/xeenx255.txt
A engines/mm/utils/engine_data.cpp
A engines/mm/utils/engine_data.h
R devtools/create_xeen/cc.cpp
R devtools/create_xeen/cc.h
R devtools/create_xeen/clouds.cpp
R devtools/create_xeen/clouds.h
R devtools/create_xeen/constants.cpp
R devtools/create_xeen/constants.h
R devtools/create_xeen/create_xeen.cpp
R devtools/create_xeen/de_constants.h
R devtools/create_xeen/en_constants.h
R devtools/create_xeen/file.h
R devtools/create_xeen/hash-str.h
R devtools/create_xeen/hashmap.cpp
R devtools/create_xeen/hashmap.h
R devtools/create_xeen/map.cpp
R devtools/create_xeen/map.h
R devtools/create_xeen/memorypool.cpp
R devtools/create_xeen/memorypool.h
R devtools/create_xeen/module.mk
R devtools/create_xeen/ru_constants.h
R devtools/create_xeen/str.cpp
R devtools/create_xeen/swords.cpp
R devtools/create_xeen/swords.h
engines/mm/module.mk
engines/mm/xeen/files.cpp
engines/mm/xeen/resources.h
diff --git a/devtools/create_xeen/cc.cpp b/devtools/create_mm/create_xeen/cc.cpp
similarity index 67%
rename from devtools/create_xeen/cc.cpp
rename to devtools/create_mm/create_xeen/cc.cpp
index 1f5ca860bc2..2059a6a50a2 100644
--- a/devtools/create_xeen/cc.cpp
+++ b/devtools/create_mm/create_xeen/cc.cpp
@@ -82,65 +82,7 @@ void CCArchive::loadIndex() {
delete[] rawIndex;
}
-void CCArchive::saveIndex() {
- // Fill up the data for the index entries into a raw data block
- byte *rawIndex = new byte[_index.size() * 8];
- byte b;
-
- byte *entryP = rawIndex;
- uint entryOffset = 8 * _index.size() + 2;
- for (uint i = 0; i < _index.size(); ++i, entryP += 8) {
- CCEntry &entry = _index[i];
- entry._offset = entryOffset;
- entryOffset += entry._size;
-
- WRITE_LE_UINT16(&entryP[0], entry._id);
- WRITE_LE_UINT32(&entryP[2], entry._offset);
- WRITE_LE_UINT16(&entryP[5], entry._size);
- entryP[7] = 0;
- }
-
- // Encrypt the index
- int seed = 0xac;
- for (uint i = 0; i < _index.size() * 8; ++i, seed += 0x67) {
- b = (rawIndex[i] - seed) & 0xff;
- b = (byte)((b >> 2) | (b << 6));
-
- assert(rawIndex[i] == (byte)((((b << 2) | (b >> 6)) + seed) & 0xff));
- rawIndex[i] = b;
- }
-
- // Write out the number of entries and the encrypted index data
- _file.writeWord(_index.size());
- _file.write(rawIndex, _index.size() * 8);
-
- delete[] rawIndex;
-}
-
-void CCArchive::saveEntries() {
- for (uint idx = 0; idx < _index.size(); ++idx) {
- CCEntry &ccEntry = _index[idx];
-
- // Encrypt the entry
- for (int i = 0; i < ccEntry._size; ++i)
- ccEntry._data[i] ^= 0x35;
-
- // Write out the entry
- _file.seek(ccEntry._offset);
- _file.write(ccEntry._data, ccEntry._size);
- }
-}
-
void CCArchive::close() {
- if (_mode == kWrite) {
- saveIndex();
- saveEntries();
- }
-}
-
-void CCArchive::add(const Common::String &name, Common::MemFile &f) {
- assert(_mode == kWrite);
- _index.push_back(CCEntry(convertNameToId(name), f.getData(), f.size()));
}
Common::MemFile CCArchive::getMember(const Common::String &name) {
diff --git a/devtools/create_xeen/cc.h b/devtools/create_mm/create_xeen/cc.h
similarity index 77%
rename from devtools/create_xeen/cc.h
rename to devtools/create_mm/create_xeen/cc.h
index 70a5eae1d30..ea4c6fcc4f9 100644
--- a/devtools/create_xeen/cc.h
+++ b/devtools/create_mm/create_xeen/cc.h
@@ -45,13 +45,10 @@ struct CCEntry {
}
};
-enum CCAccess { kRead = 0, kWrite = 1 };
-
class CCArchive {
private:
Common::Array<CCEntry> _index;
Common::File &_file;
- CCAccess _mode;
private:
/**
* Convert a resource name to it's equivalent hash key
@@ -62,41 +59,22 @@ private:
* Loads an index from the file
*/
void loadIndex();
-
- /**
- * Saves the index to the file
- */
- void saveIndex();
-
- /**
- * Saves the individual entries to the file
- */
- void saveEntries();
public:
/**
* Constructor
*/
- CCArchive(Common::File &file, CCAccess mode) : _file(file), _mode(mode) {
- if (mode == kRead)
- loadIndex();
+ CCArchive(Common::File &file) : _file(file) {
+ loadIndex();
}
~CCArchive() {
_file.close();
}
- /**
- * In write mode, finishes the CC file, writing out the resulting content
- */
void close();
/**
- * Adds an entry to the CC
- */
- void add(const Common::String &name, Common::MemFile &f);
-
- /**
- * In read mode, gets a member
+ * Gets a member
*/
Common::MemFile getMember(const Common::String &name);
};
diff --git a/devtools/create_xeen/clouds.cpp b/devtools/create_mm/create_xeen/clouds.cpp
similarity index 88%
rename from devtools/create_xeen/clouds.cpp
rename to devtools/create_mm/create_xeen/clouds.cpp
index 8bdfffc86df..f82e02b1930 100644
--- a/devtools/create_xeen/clouds.cpp
+++ b/devtools/create_mm/create_xeen/clouds.cpp
@@ -22,8 +22,9 @@
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
-#include "file.h"
#include "clouds.h"
+#include "cc.h"
+#include "file.h"
static const char *const MAP_NAMES[86] = {
"", "Area A1", "Area A2", "Area A3", "Area A4", "Area B1", "Area B2",
@@ -52,10 +53,10 @@ static const char *const MAP_NAMES[86] = {
"The Warzone"
};
-void writeCloudsData(CCArchive &cc, const char *darkName) {
+void writeCloudsData(const char *darkName) {
Common::File darkFile;
if (darkFile.open(darkName, Common::kFileReadMode)) {
- CCArchive darkCc(darkFile, kRead);
+ CCArchive darkCc(darkFile);
Common::MemFile mae = darkCc.getMember("mae.xen");
Common::MemFile spells = darkCc.getMember("spells.xen");
@@ -64,17 +65,17 @@ void writeCloudsData(CCArchive &cc, const char *darkName) {
Common::MemFile wallPics = darkCc.getMember("xeenpic.dat");
Common::MemFile mirror = darkCc.getMember("xeenmirr.txt");
- cc.add("mae.cld", mae);
- cc.add("spells.cld", spells);
- cc.add("animinfo.cld", animInfo);
- cc.add("monsters.cld", monsters);
- cc.add("wallpics.cld", wallPics);
- cc.add("xeenmirr.txt", mirror);
+ Common::File::write("mae.cld", mae);
+ Common::File::write("spells.cld", spells);
+ Common::File::write("animinfo.cld", animInfo);
+ Common::File::write("monsters.cld", monsters);
+ Common::File::write("wallpics.cld", wallPics);
+ Common::File::write("xeenmirr.txt", mirror);
Common::MemFile mapNames;
for (int idx = 0; idx < 86; ++idx)
mapNames.syncString(MAP_NAMES[idx]);
- cc.add("mapnames.cld", mapNames);
+ Common::File::write("mapnames.cld", mapNames);
darkFile.close();
} else {
diff --git a/devtools/create_xeen/clouds.h b/devtools/create_mm/create_xeen/clouds.h
similarity index 89%
rename from devtools/create_xeen/clouds.h
rename to devtools/create_mm/create_xeen/clouds.h
index a704ac6e496..5a031253a87 100644
--- a/devtools/create_xeen/clouds.h
+++ b/devtools/create_mm/create_xeen/clouds.h
@@ -22,9 +22,6 @@
#ifndef CLOUDS_H
#define CLOUDS_H
-#include "common/scummsys.h"
-#include "cc.h"
-
-extern void writeCloudsData(CCArchive &cc, const char *darkName);
+extern void writeCloudsData(const char *darkName);
#endif
diff --git a/devtools/create_xeen/constants.cpp b/devtools/create_mm/create_xeen/constants.cpp
similarity index 99%
rename from devtools/create_xeen/constants.cpp
rename to devtools/create_mm/create_xeen/constants.cpp
index 3fad7077b8e..a61e10798cf 100644
--- a/devtools/create_xeen/constants.cpp
+++ b/devtools/create_mm/create_xeen/constants.cpp
@@ -830,7 +830,7 @@ const char *const LangConstants::MUSIC_FILES2[6][7] = {
};
-void LangConstants::writeConstants(Common::String num, CCArchive &cc) {
+void LangConstants::writeConstants(Common::String num) {
Common::MemFile file;
file.syncString(CLOUDS_CREDITS());
file.syncString(DARK_SIDE_CREDITS());
@@ -1195,7 +1195,8 @@ void LangConstants::writeConstants(Common::String num, CCArchive &cc) {
file.syncStrings(CLOUDS_MONSTERS(), 91);
file.syncStrings(CLOUDS_SPELLS(), 77);
- cc.add("CONSTANTS" + num, file);
+ Common::String fname = "CONSTANTS" + num;
+ Common::File::write(fname.c_str(), file);
Common::MemFile keys;
keys.syncNumber(keyConstants()->dialogsCharInfo()->KEY_ITEM());
@@ -1281,14 +1282,15 @@ void LangConstants::writeConstants(Common::String num, CCArchive &cc) {
keys.syncNumber(keyConstants()->cloudsOfXeenMenu()->KEY_SHOW_CREDITS());
keys.syncNumber(keyConstants()->cloudsOfXeenMenu()->KEY_VIEW_ENDGAME());
- cc.add("CONSTKEYS" + num, keys);
+ fname = "CONSTKEYS" + num;
+ Common::File::write(fname.c_str(), keys);
}
-void writeConstants(CCArchive &cc) {
+void writeConstants() {
EN eng;
- eng.writeConstants(Common::String::format("_%i", 7 /*Common::EN_ANY */), cc);
+ eng.writeConstants(Common::String::format("_%i", 7 /*Common::EN_ANY */));
RU ru;
- ru.writeConstants(Common::String::format("_%i", 26 /* Common::RU_RUS */), cc);
+ ru.writeConstants(Common::String::format("_%i", 26 /* Common::RU_RUS */));
DE de;
- de.writeConstants(Common::String::format("_%i", 4 /* Common::DE_DEU */), cc);
+ de.writeConstants(Common::String::format("_%i", 4 /* Common::DE_DEU */));
}
diff --git a/devtools/create_xeen/constants.h b/devtools/create_mm/create_xeen/constants.h
similarity index 99%
rename from devtools/create_xeen/constants.h
rename to devtools/create_mm/create_xeen/constants.h
index 744dca08b27..09917165b08 100644
--- a/devtools/create_xeen/constants.h
+++ b/devtools/create_mm/create_xeen/constants.h
@@ -472,7 +472,7 @@ public:
virtual const char **CLOUDS_MONSTERS() = 0;
virtual const char **CLOUDS_SPELLS() = 0;
- void writeConstants(Common::String num, CCArchive &cc);
+ void writeConstants(Common::String num);
class KeyConstants {
public:
@@ -618,6 +618,6 @@ public:
virtual KeyConstants *keyConstants() = 0;
};
-extern void writeConstants(CCArchive &cc);
+extern void writeConstants();
#endif
diff --git a/devtools/create_xeen/create_xeen.cpp b/devtools/create_mm/create_xeen/create_xeen.cpp
similarity index 76%
rename from devtools/create_xeen/create_xeen.cpp
rename to devtools/create_mm/create_xeen/create_xeen.cpp
index 9f84b9f61cf..82798cde375 100644
--- a/devtools/create_xeen/create_xeen.cpp
+++ b/devtools/create_mm/create_xeen/create_xeen.cpp
@@ -32,8 +32,6 @@
#include "constants.h"
#include "map.h"
-#define VERSION_NUMBER 5
-
void NORETURN_PRE error(const char *s, ...) {
va_list ap;
@@ -46,33 +44,35 @@ void NORETURN_PRE error(const char *s, ...) {
exit(1);
}
-static void writeVersion(CCArchive &cc) {
- Common::MemFile f;
- f.writeLong(VERSION_NUMBER);
- cc.add("VERSION", f);
+static void writeVersion() {
+ Common::File f;
+ if (!f.open("version.txt", Common::kFileWriteMode))
+ error("Could not create version.txt");
+
+ f.write("1.0\n", 4);
+ f.close();
}
+/**
+ * Creates the different files in the xeen/ subfolder of
+ * the files/ folder. The files folder overall is zipped
+ * up to form the xeen data file
+ */
int main(int argc, char *argv[]) {
if (argc != 3) {
error("Format: %s dark.cc \"swords xeen.dat\"", argv[0]);
}
- Common::File outputFile;
- if (!outputFile.open("xeen.ccs", Common::kFileWriteMode)) {
- error("Could not open input file");
- }
-
- CCArchive cc(outputFile, kWrite);
- writeVersion(cc);
- writeConstants(cc);
- writeMap(cc);
+ writeVersion();
+ writeConstants();
+ writeMap();
const char *darkName = argv[1];
- writeCloudsData(cc, darkName);
+ writeCloudsData(darkName);
const char *swordsDatName = argv[2];
- writeSwordsData(cc, swordsDatName);
+ writeSwordsData(swordsDatName);
- cc.close();
+ printf("File creation done");
return 0;
}
diff --git a/devtools/create_xeen/de_constants.h b/devtools/create_mm/create_xeen/de_constants.h
similarity index 99%
rename from devtools/create_xeen/de_constants.h
rename to devtools/create_mm/create_xeen/de_constants.h
index 28e479b597d..7d4b158e9bb 100644
--- a/devtools/create_xeen/de_constants.h
+++ b/devtools/create_mm/create_xeen/de_constants.h
@@ -1941,16 +1941,12 @@ public:
}
const char **CLOUDS_MAE_NAMES() {
- static const char *_maeNames[] = {
- "",
- };
+ static const char *_maeNames[131] = { "" };
return _maeNames;
}
const char **CLOUDS_MIRROR_LOCATIONS() {
- static const char *_mirrLocs[] = {
- "",
- };
+ static const char *_mirrLocs[59] = { "" };
return _mirrLocs;
}
@@ -1962,16 +1958,12 @@ public:
}
const char **CLOUDS_MONSTERS() {
- static const char *_monsters[] = {
- "",
- };
+ static const char *_monsters[91] = { "" };
return _monsters;
}
const char **CLOUDS_SPELLS() {
- static const char *_spells[] = {
- "",
- };
+ static const char *_spells[77] = { "" };
return _spells;
}
diff --git a/devtools/create_xeen/en_constants.h b/devtools/create_mm/create_xeen/en_constants.h
similarity index 99%
rename from devtools/create_xeen/en_constants.h
rename to devtools/create_mm/create_xeen/en_constants.h
index 9c79ab7aa7d..c6111fdc380 100644
--- a/devtools/create_xeen/en_constants.h
+++ b/devtools/create_mm/create_xeen/en_constants.h
@@ -1941,16 +1941,12 @@ public:
}
const char **CLOUDS_MAE_NAMES() {
- static const char *_maeNames[] = {
- "",
- };
+ static const char *_maeNames[131] = { "" };
return _maeNames;
}
const char **CLOUDS_MIRROR_LOCATIONS() {
- static const char *_mirrLocs[] = {
- "",
- };
+ static const char *_mirrLocs[59] = { "" };
return _mirrLocs;
}
@@ -1962,16 +1958,12 @@ public:
}
const char **CLOUDS_MONSTERS() {
- static const char *_monsters[] = {
- "",
- };
+ static const char *_monsters[91] = { "" };
return _monsters;
}
const char **CLOUDS_SPELLS() {
- static const char *_spells[] = {
- "",
- };
+ static const char *_spells[77] = { "" };
return _spells;
}
diff --git a/devtools/create_xeen/file.h b/devtools/create_mm/create_xeen/file.h
similarity index 90%
rename from devtools/create_xeen/file.h
rename to devtools/create_mm/create_xeen/file.h
index 0559082e0a9..18baf35a454 100644
--- a/devtools/create_xeen/file.h
+++ b/devtools/create_mm/create_xeen/file.h
@@ -33,6 +33,9 @@
namespace Common {
+#define MAX_MEM_SIZE 65536
+#define BUFFER_SIZE 16384
+
enum AccessMode {
kFileReadMode = 1,
kFileWriteMode = 2
@@ -125,50 +128,6 @@ public:
}
};
-class File : public Stream {
-private:
- ::FILE *_f;
-public:
- File() : _f(nullptr) {}
- virtual ~File() { close(); }
-
- bool open(const char *filename, AccessMode mode = kFileReadMode) {
- _f = fopen(filename, (mode == kFileReadMode) ? "rb" : "wb+");
- return (_f != NULL);
- }
- void close() {
- if (_f)
- fclose(_f);
- _f = nullptr;
- }
-
- virtual int seek(int offset, int whence = SEEK_SET) {
- return fseek(_f, offset, whence);
- }
- virtual long read(void *buffer, size_t len) {
- return fread(buffer, 1, len, _f);
- }
- virtual void write(const void *buffer, size_t len) {
- assert(_f);
- fwrite(buffer, 1, len, _f);
- }
- virtual uint pos() const {
- return ftell(_f);
- }
- virtual uint size() const {
- uint currentPos = pos();
- fseek(_f, 0, SEEK_END);
- uint result = pos();
- fseek(_f, currentPos, SEEK_SET);
- return result;
- }
- virtual bool eof() const {
- return feof(_f) != 0;
- }
-};
-
-#define MAX_MEM_SIZE 65536
-
class MemFile : public Stream {
private:
byte _data[MAX_MEM_SIZE];
@@ -180,7 +139,8 @@ public:
MemFile(const byte *data, size_t size) : _size(size), _offset(0) {
memcpy(_data, data, size);
}
- virtual ~MemFile() {}
+ virtual ~MemFile() {
+ }
bool open() {
memset(_data, 0, MAX_MEM_SIZE);
@@ -202,8 +162,9 @@ public:
return _offset;
}
virtual long read(void *buffer, size_t len) {
- len = MAX(len, _size - _offset);
+ len = MIN(len, _size - _offset);
memcpy(buffer, &_data[_offset], len);
+ _offset += len;
return len;
}
virtual void write(const void *buffer, size_t len) {
@@ -222,7 +183,9 @@ public:
return _offset >= _size;
}
- const byte *getData() const { return _data; }
+ const byte *getData() const {
+ return _data;
+ }
void syncString(const char *str) {
write(str, strlen(str) + 1);
@@ -266,6 +229,70 @@ public:
}
};
+class File : public Stream {
+private:
+ ::FILE *_f;
+public:
+ File() : _f(nullptr) {}
+ virtual ~File() { close(); }
+
+ bool open(const char *filename, AccessMode mode = kFileReadMode) {
+ if (mode == kFileReadMode) {
+ _f = fopen(filename, "rb");
+ } else {
+ char fname[256];
+ sprintf(fname, "../files/xeen/%s", filename);
+ _f = fopen(fname, "wb+");
+ }
+
+ return (_f != NULL);
+ }
+ void close() {
+ if (_f)
+ fclose(_f);
+ _f = nullptr;
+ }
+
+ virtual int seek(int offset, int whence = SEEK_SET) {
+ return fseek(_f, offset, whence);
+ }
+ virtual long read(void *buffer, size_t len) {
+ return fread(buffer, 1, len, _f);
+ }
+ virtual void write(const void *buffer, size_t len) {
+ assert(_f);
+ fwrite(buffer, 1, len, _f);
+ }
+ virtual uint pos() const {
+ return ftell(_f);
+ }
+ virtual uint size() const {
+ uint currentPos = pos();
+ fseek(_f, 0, SEEK_END);
+ uint result = pos();
+ fseek(_f, currentPos, SEEK_SET);
+ return result;
+ }
+ virtual bool eof() const {
+ return feof(_f) != 0;
+ }
+
+ static void write(const char *fname, MemFile &src) {
+ File f;
+ if (!f.open(fname, kFileWriteMode)) {
+ printf("Could not open %s for writing", fname);
+ exit(1);
+ }
+ src.seek(0);
+ char buffer[BUFFER_SIZE];
+ size_t count = 0;
+
+ while ((count = src.read(buffer, BUFFER_SIZE)) != 0) {
+ f.write(buffer, count);
+ }
+ }
+};
+
} // End of namespace Common
#endif
diff --git a/devtools/create_xeen/hash-str.h b/devtools/create_mm/create_xeen/hash-str.h
similarity index 100%
rename from devtools/create_xeen/hash-str.h
rename to devtools/create_mm/create_xeen/hash-str.h
diff --git a/devtools/create_xeen/hashmap.cpp b/devtools/create_mm/create_xeen/hashmap.cpp
similarity index 100%
rename from devtools/create_xeen/hashmap.cpp
rename to devtools/create_mm/create_xeen/hashmap.cpp
diff --git a/devtools/create_xeen/hashmap.h b/devtools/create_mm/create_xeen/hashmap.h
similarity index 100%
rename from devtools/create_xeen/hashmap.h
rename to devtools/create_mm/create_xeen/hashmap.h
diff --git a/devtools/create_xeen/map.cpp b/devtools/create_mm/create_xeen/map.cpp
similarity index 89%
rename from devtools/create_xeen/map.cpp
rename to devtools/create_mm/create_xeen/map.cpp
index 6d5c8fb8f98..be34747ad81 100644
--- a/devtools/create_xeen/map.cpp
+++ b/devtools/create_mm/create_xeen/map.cpp
@@ -59,7 +59,7 @@ static const byte SURFACE_TYPES_255[16] = { 1, 1, 2, 3, 4, 0, 6, 7, 0, 9, 0, 0,
/**
* Write out new mirror entries
*/
-static void writeMirrorText(CCArchive &cc) {
+static void writeMirrorText() {
Common::MemFile f;
for (int idx = 0; idx < MIRROR_COUNT; ++idx) {
@@ -71,13 +71,13 @@ static void writeMirrorText(CCArchive &cc) {
f.writeByte(me._direction);
}
- cc.add("xeenmirr.ext", f);
+ Common::File::write("xeenmirr.ext", f);
}
/**
* Write out the maze
*/
-static void writeMaze(CCArchive &cc) {
+static void writeMaze() {
Common::MemFile f;
// Wall data
@@ -106,26 +106,26 @@ static void writeMaze(CCArchive &cc) {
f.writeByte(0, MAP_WIDTH * MAP_HEIGHT / 8); // Seen tiles
f.writeByte(0, MAP_WIDTH * MAP_HEIGHT / 8); // Stepped on tiles
- cc.add("mazex255.dat", f);
+ Common::File::write("mazex255.dat", f);
}
/**
* Write out the maze name
*/
-static void writeMazeName(CCArchive &cc) {
+static void writeMazeName() {
Common::MemFile f;
char mazeName[33];
memset(mazeName, 0, 33);
strcpy(mazeName, "ScummVM");
f.write(mazeName, 33);
- cc.add("xeenx255.txt", f);
+ Common::File::write("xeenx255.txt", f);
}
/**
* Write out maze events
*/
-static void writeMazeEvents(CCArchive &cc) {
+static void writeMazeEvents() {
Common::MemFile f;
// Mirror events
@@ -151,13 +151,13 @@ static void writeMazeEvents(CCArchive &cc) {
f.write(BENCH1_EVENTS, 32);
f.write(BENCH2_EVENTS, 30);
- cc.add("mazex255.evt", f);
+ Common::File::write("mazex255.evt", f);
}
/**
* Write out maze event text
*/
-static void writeMazeText(CCArchive &cc) {
+static void writeMazeText() {
Common::MemFile f;
f.writeString("Where to?");
@@ -165,13 +165,13 @@ static void writeMazeText(CCArchive &cc) {
f.writeString("You have done well to find this ancient isle. This will aid you on your journey.");
f.writeString("It is my hope that this isle will be but the first of many such new destinations the mirror may take you.");
- cc.add("aazex255.txt", f);
+ Common::File::write("aazex255.txt", f);
}
/**
* Write out the monster/object data
*/
-static void writeMonstersObjects(CCArchive &cc) {
+static void writeMonstersObjects() {
Common::MemFile f;
f.writeByte(8); // Object sprites
f.writeByte(2);
@@ -220,27 +220,27 @@ static void writeMonstersObjects(CCArchive &cc) {
}
}
- cc.add("mazex255.mob", f);
+ Common::File::write("mazex255.mob", f);
}
/**
* Write out the data for the head danger senses
*/
-static void writeHeadData(CCArchive &cc) {
+static void writeHeadData() {
Common::MemFile f;
f.writeByte(0, MAP_HEIGHT * MAP_HEIGHT * 2);
- cc.add("aazex255.hed", f);
+ Common::File::write("aazex255.hed", f);
}
/**
* Write out the new ScummVM map
*/
-void writeMap(CCArchive &cc) {
- writeMirrorText(cc);
- writeMaze(cc);
- writeMazeName(cc);
- writeMazeEvents(cc);
- writeMazeText(cc);
- writeMonstersObjects(cc);
- writeHeadData(cc);
+void writeMap() {
+ writeMirrorText();
+ writeMaze();
+ writeMazeName();
+ writeMazeEvents();
+ writeMazeText();
+ writeMonstersObjects();
+ writeHeadData();
}
diff --git a/devtools/create_xeen/map.h b/devtools/create_mm/create_xeen/map.h
similarity index 96%
rename from devtools/create_xeen/map.h
rename to devtools/create_mm/create_xeen/map.h
index c2d6d3c81fd..765fdb51618 100644
--- a/devtools/create_xeen/map.h
+++ b/devtools/create_mm/create_xeen/map.h
@@ -32,6 +32,6 @@ struct MirrorEntry {
byte _direction;
};
-extern void writeMap(CCArchive &cc);
+extern void writeMap();
#endif
diff --git a/devtools/create_xeen/memorypool.cpp b/devtools/create_mm/create_xeen/memorypool.cpp
similarity index 100%
rename from devtools/create_xeen/memorypool.cpp
rename to devtools/create_mm/create_xeen/memorypool.cpp
diff --git a/devtools/create_xeen/memorypool.h b/devtools/create_mm/create_xeen/memorypool.h
similarity index 100%
rename from devtools/create_xeen/memorypool.h
rename to devtools/create_mm/create_xeen/memorypool.h
diff --git a/devtools/create_xeen/module.mk b/devtools/create_mm/create_xeen/module.mk
similarity index 77%
rename from devtools/create_xeen/module.mk
rename to devtools/create_mm/create_xeen/module.mk
index eabd739b4fe..6d5058cf945 100644
--- a/devtools/create_xeen/module.mk
+++ b/devtools/create_mm/create_xeen/module.mk
@@ -1,4 +1,4 @@
-MODULE := devtools/create_xeen
+MODULE := devtools/create_mm
MODULE_OBJS := \
create_xeen.o \
@@ -12,7 +12,7 @@ MODULE_OBJS := \
swords.o
# Set the name of the executable
-TOOL_EXECUTABLE := create_xeen
+TOOL_EXECUTABLE := create_mm
# Include common rules
include $(srcdir)/rules.mk
diff --git a/devtools/create_xeen/ru_constants.h b/devtools/create_mm/create_xeen/ru_constants.h
similarity index 99%
rename from devtools/create_xeen/ru_constants.h
rename to devtools/create_mm/create_xeen/ru_constants.h
index 0acda531334..f0fb49f3c21 100644
--- a/devtools/create_xeen/ru_constants.h
+++ b/devtools/create_mm/create_xeen/ru_constants.h
@@ -1948,7 +1948,7 @@ public:
}
const char **CLOUDS_MAE_NAMES() { // mae.cld
- static const char *_maeNames[] = {
+ static const char *_maeNames[131] = {
" ",
"\xA6\xA0\xE0\xA0 ", //жаÑа
"\xAE\xA3\xAD\xA5\xA9 ", //огней
@@ -2085,7 +2085,7 @@ public:
}
const char **CLOUDS_MIRROR_LOCATIONS() { // xeenmirr.txt
- static const char *_mirrLocs[] = {
+ static const char *_mirrLocs[59] = {
"\xA2\xA5\xE0\xE2\xA8\xA3\xAE", // веÑÑиго
"\xAD\xA0\xA9\xE2\xE8\xED\xA4\xAE\xE3", // найÑÑÑдоÑ
"\xE0\xA8\xA2\xA5\xE0\xE1\xA8\xE2\xA8", // ÑивеÑÑиÑи
@@ -2242,7 +2242,7 @@ public:
}
const char **CLOUDS_MONSTERS() { // monsters.cld
- static const char *_monsters[] = {
+ static const char *_monsters[91] = {
"\x91\xAB\xA8\xA7\xA5\xAD\xEC ", // СлизенÑ
"\x81\xAE\xAB\xEC\xE8\xA0\xEF \xAB\xA5\xE2\xE3\xE7\xA0\xEF \xAC\xEB\xE8\xEC ", // ÐолÑÑÐ°Ñ Ð»ÐµÑÑÑÐ°Ñ Ð¼ÑÑÑ
"\x97\xE3\xA4\xAE\xA2\xA8\xE9\xAD\xA0\xEF \xE1\xA0\xE0\xA0\xAD\xE7\xA0 ", // ЧÑдовиÑÐ½Ð°Ñ ÑаÑанÑа
@@ -2339,7 +2339,7 @@ public:
}
const char **CLOUDS_SPELLS() { // spells.cld
- static const char *_spells[] = {
+ static const char *_spells[77] = {
"\x90\xA0\xE1\xAF\xEB\xAB\xA5\xAD\xA8\xA5 \xAA\xA8\xE1\xAB\xAE\xE2\xEB ", // РаÑпÑление киÑлоÑÑ
"\x8F\xE0\xAE\xA1\xE3\xA6\xA4\xA5\xAD\xA8\xA5 ", // ÐÑобÑждение
"\x8F\xAE\xA2\xA5\xAB\xA8\xE2\xA5\xAB\xEC \xA7\xA2\xA5\xE0\xA5\xA9 ", // ÐовелиÑÐµÐ»Ñ Ð·Ð²ÐµÑей
diff --git a/devtools/create_mm/create_xeen/str.cpp b/devtools/create_mm/create_xeen/str.cpp
new file mode 100644
index 00000000000..26a3f16ef66
--- /dev/null
+++ b/devtools/create_mm/create_xeen/str.cpp
@@ -0,0 +1,3 @@
+#define SCUMMVM_UTIL
+#include "../../../common/base-str.cpp"
+#include "../../../common/str.cpp"
diff --git a/devtools/create_mm/create_xeen/str.h b/devtools/create_mm/create_xeen/str.h
new file mode 100644
index 00000000000..3e73750e485
--- /dev/null
+++ b/devtools/create_mm/create_xeen/str.h
@@ -0,0 +1,385 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef COMMON_STRING_H
+#define COMMON_STRING_H
+
+#include "common/scummsys.h"
+
+#include <stdarg.h>
+
+namespace Common {
+
+/**
+ * Simple string class for ScummVM. Provides automatic storage managment,
+ * and overloads several operators in a 'natural' fashion, mimicking
+ * the std::string class. Even provides simple iterators.
+ *
+ * This class tries to avoid allocating lots of small blocks on the heap,
+ * since that is inefficient on several platforms supported by ScummVM.
+ * Instead, small strings are stored 'inside' the string object (i.e. on
+ * the stack, for stack allocated objects), and only for strings exceeding
+ * a certain length do we allocate a buffer on the heap.
+ *
+ * The presence of \0 characters in the string will cause undefined
+ * behavior in some operations.
+ */
+class String {
+public:
+ static const uint32 npos = 0xFFFFFFFF;
+protected:
+ /**
+ * The size of the internal storage. Increasing this means less heap
+ * allocations are needed, at the cost of more stack memory usage,
+ * and of course lots of wasted memory. Empirically, 90% or more of
+ * all String instances are less than 32 chars long. If a platform
+ * is very short on stack space, it would be possible to lower this.
+ * A value of 24 still seems acceptable, though considerably worse,
+ * while 16 seems to be the lowest you want to go... Anything lower
+ * than 8 makes no sense, since that's the size of member _extern
+ * (on 32 bit machines; 12 bytes on systems with 64bit pointers).
+ */
+ static const uint32 _builtinCapacity = 32 - sizeof(uint32) - sizeof(char *);
+
+ /**
+ * Length of the string. Stored to avoid having to call strlen
+ * a lot. Yes, we limit ourselves to strings shorter than 4GB --
+ * on purpose :-).
+ */
+ uint32 _size;
+
+ /**
+ * Pointer to the actual string storage. Either points to _storage,
+ * or to a block allocated on the heap via malloc.
+ */
+ char *_str;
+
+
+ union {
+ /**
+ * Internal string storage.
+ */
+ char _storage[_builtinCapacity];
+ /**
+ * External string storage data -- the refcounter, and the
+ * capacity of the string _str points to.
+ */
+ struct {
+ mutable int *_refCount;
+ uint32 _capacity;
+ } _extern;
+ };
+
+ inline bool isStorageIntern() const {
+ return _str == _storage;
+ }
+
+public:
+ /** Construct a new empty string. */
+ String() : _size(0), _str(_storage) { _storage[0] = 0; }
+
+ /** Construct a new string from the given NULL-terminated C string. */
+ String(const char *str);
+
+ /** Construct a new string containing exactly len characters read from address str. */
+ String(const char *str, uint32 len);
+
+ /** Construct a new string containing the characters between beginP (including) and endP (excluding). */
+ String(const char *beginP, const char *endP);
+
+ /** Construct a copy of the given string. */
+ String(const String &str);
+
+ /** Construct a string consisting of the given character. */
+ explicit String(char c);
+
+ ~String();
+
+ String &operator=(const char *str);
+ String &operator=(const String &str);
+ String &operator=(char c);
+ String &operator+=(const char *str);
+ String &operator+=(const String &str);
+ String &operator+=(char c);
+
+ bool operator==(const String &x) const;
+ bool operator==(const char *x) const;
+ bool operator!=(const String &x) const;
+ bool operator!=(const char *x) const;
+
+ bool operator<(const String &x) const;
+ bool operator<=(const String &x) const;
+ bool operator>(const String &x) const;
+ bool operator>=(const String &x) const;
+
+ bool equals(const String &x) const;
+ bool equalsIgnoreCase(const String &x) const;
+ int compareTo(const String &x) const; // strcmp clone
+ int compareToIgnoreCase(const String &x) const; // stricmp clone
+
+ bool equals(const char *x) const;
+ bool equalsIgnoreCase(const char *x) const;
+ int compareTo(const char *x) const; // strcmp clone
+ int compareToIgnoreCase(const char *x) const; // stricmp clone
+
+ bool hasSuffix(const String &x) const;
+ bool hasSuffix(const char *x) const;
+
+ bool hasPrefix(const String &x) const;
+ bool hasPrefix(const char *x) const;
+
+ bool contains(const String &x) const;
+ bool contains(const char *x) const;
+ bool contains(char x) const;
+
+ inline const char *c_str() const { return _str; }
+ inline uint size() const { return _size; }
+
+ inline bool empty() const { return (_size == 0); }
+ char firstChar() const { return (_size > 0) ? _str[0] : 0; }
+ char lastChar() const { return (_size > 0) ? _str[_size - 1] : 0; }
+
+ char operator[](int idx) const {
+ assert(_str && idx >= 0 && idx < (int)_size);
+ return _str[idx];
+ }
+
+ /** Remove the last character from the string. */
+ void deleteLastChar();
+
+ /** Remove the character at position p from the string. */
+ void deleteChar(uint32 p);
+
+ /** Remove all characters from position p to the p + len. If len = String::npos, removes all characters to the end */
+ void erase(uint32 p, uint32 len = npos);
+
+ /** Set character c at position p, replacing the previous character there. */
+ void setChar(char c, uint32 p);
+
+ /** Insert character c before position p. */
+ void insertChar(char c, uint32 p);
+
+ /** Clears the string, making it empty. */
+ void clear();
+
+ /** Convert all characters in the string to lowercase. */
+ void toLowercase();
+
+ /** Convert all characters in the string to uppercase. */
+ void toUppercase();
+
+ /**
+ * Removes trailing and leading whitespaces. Uses isspace() to decide
+ * what is whitespace and what not.
+ */
+ void trim();
+
+ uint hash() const;
+
+ /**
+ * Print formatted data into a String object. Similar to sprintf,
+ * except that it stores the result in (variably sized) String
+ * instead of a fixed size buffer.
+ */
+ static String format(const char *fmt, ...) GCC_PRINTF(1,2);
+
+ /**
+ * Print formatted data into a String object. Similar to vsprintf,
+ * except that it stores the result in (variably sized) String
+ * instead of a fixed size buffer.
+ */
+ static String vformat(const char *fmt, va_list args);
+
+public:
+ typedef char value_type;
+ /**
+ * Unsigned version of the underlying type. This can be used to cast
+ * individual string characters to bigger integer types without sign
+ * extension happening.
+ */
+ typedef unsigned char unsigned_type;
+ typedef char * iterator;
+ typedef const char * const_iterator;
+
+ iterator begin() {
+ // Since the user could potentially
+ // change the string via the returned
+ // iterator we have to assure we are
+ // pointing to a unique storage.
+ makeUnique();
+
+ return _str;
+ }
+
+ iterator end() {
+ return begin() + size();
+ }
+
+ const_iterator begin() const {
+ return _str;
+ }
+
+ const_iterator end() const {
+ return begin() + size();
+ }
+
+protected:
+ void makeUnique();
+ void ensureCapacity(uint32 new_size, bool keep_old);
+ void incRefCount() const;
+ void decRefCount(int *oldRefCount);
+ void initWithCStr(const char *str, uint32 len);
+};
+
+// Append two strings to form a new (temp) string
+String operator+(const String &x, const String &y);
+
+String operator+(const char *x, const String &y);
+String operator+(const String &x, const char *y);
+
+String operator+(const String &x, char y);
+String operator+(char x, const String &y);
+
+// Some useful additional comparison operators for Strings
+bool operator==(const char *x, const String &y);
+bool operator!=(const char *x, const String &y);
+
+// Utility functions to remove leading and trailing whitespaces
+extern char *ltrim(char *t);
+extern char *rtrim(char *t);
+extern char *trim(char *t);
+
+
+/**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return 'bar.txt'
+ * /foo/bar/ would return 'bar'
+ * /foo/./bar// would return 'bar'
+ *
+ * @param path the path of which we want to know the last component
+ * @param sep character used to separate path components
+ * @return The last component of the path.
+ */
+String lastPathComponent(const String &path, const char sep);
+
+/**
+ * Normalize a given path to a canonical form. In particular:
+ * - trailing separators are removed: /foo/bar/ -> /foo/bar
+ * - double separators (= empty components) are removed: /foo//bar -> /foo/bar
+ * - dot components are removed: /foo/./bar -> /foo/bar
+ *
+ * @todo remove double dot components: /foo/baz/../bar -> /foo/bar
+ *
+ * @param path the path to normalize
+ * @param sep the separator token (usually '/' on Unix-style systems, or '\\' on Windows based stuff)
+ * @return the normalized path
+ */
+String normalizePath(const String &path, const char sep);
+
+
+/**
+ * Simple DOS-style pattern matching function (understands * and ? like used in DOS).
+ * Taken from exult/files/listfiles.cc
+ *
+ * Token meaning:
+ * "*": any character, any amount of times.
+ * "?": any character, only once.
+ * "#": any decimal digit, only once.
+ *
+ * Example strings/patterns:
+ * String: monkey.s01 Pattern: monkey.s?? => true
+ * String: monkey.s101 Pattern: monkey.s?? => false
+ * String: monkey.s99 Pattern: monkey.s?1 => false
+ * String: monkey.s101 Pattern: monkey.s* => true
+ * String: monkey.s99 Pattern: monkey.s*1 => false
+ * String: monkey.s01 Pattern: monkey.s## => true
+ * String: monkey.s01 Pattern: monkey.### => false
+ *
+ * @param str Text to be matched against the given pattern.
+ * @param pat Glob pattern.
+ * @param ignoreCase Whether to ignore the case when doing pattern match
+ * @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly.
+ *
+ * @return true if str matches the pattern, false otherwise.
+ */
+bool matchString(const char *str, const char *pat, bool ignoreCase = false, bool pathMode = false);
+
+
+/**
+ * Take a 32 bit value and turn it into a four character string, where each of
+ * the four bytes is turned into one character. Most significant byte is printed
+ * first.
+ */
+String tag2string(uint32 tag);
+
+/**
+ * Copy up to size - 1 characters from src to dst and also zero terminate the
+ * result. Note that src must be a zero terminated string.
+ *
+ * In case size is zero this function just returns the length of the source
+ * string.
+ *
+ * @note This is modeled after OpenBSD's strlcpy. See the manpage here:
+ * https://man.openbsd.org/strlcpy
+ *
+ * @param dst The destination buffer.
+ * @param src The source string.
+ * @param size The size of the destination buffer.
+ * @return The length of the (non-truncated) result, i.e. strlen(src).
+ */
+size_t strlcpy(char *dst, const char *src, size_t size);
+
+/**
+ * Append the string src to the string dst. Note that both src and dst must be
+ * zero terminated. The result will be zero terminated. At most
+ * "size - strlen(dst) - 1" bytes will be appended.
+ *
+ * In case the dst string does not contain a zero within the first "size" bytes
+ * the dst string will not be changed and size + strlen(src) is returned.
+ *
+ * @note This is modeled after OpenBSD's strlcat. See the manpage here:
+ * https://man.openbsd.org/strlcat
+ *
+ * @param dst The string the source string should be appended to.
+ * @param src The source string.
+ * @param size The (total) size of the destination buffer.
+ * @return The length of the (non-truncated) result. That is
+ * strlen(dst) + strlen(src). In case strlen(dst) > size
+ * size + strlen(src) is returned.
+ */
+size_t strlcat(char *dst, const char *src, size_t size);
+
+/**
+ * Convenience wrapper for tag2string which "returns" a C string.
+ * Note: It is *NOT* safe to do anything with the return value other than directly
+ * copying or printing it.
+ */
+#define tag2str(x) Common::tag2string(x).c_str()
+
+
+} // End of namespace Common
+
+extern int scumm_stricmp(const char *s1, const char *s2);
+extern int scumm_strnicmp(const char *s1, const char *s2, uint n);
+
+#endif
diff --git a/devtools/create_xeen/swords.cpp b/devtools/create_mm/create_xeen/swords.cpp
similarity index 91%
rename from devtools/create_xeen/swords.cpp
rename to devtools/create_mm/create_xeen/swords.cpp
index f679880a4de..337434d92ea 100644
--- a/devtools/create_xeen/swords.cpp
+++ b/devtools/create_mm/create_xeen/swords.cpp
@@ -27,7 +27,9 @@
#define MONSTERS_COUNT 150
-void writeSwordsData(CCArchive &cc, const char *swordsDatName) {
+extern void NORETURN_PRE error(const char *s, ...);
+
+void writeSwordsData(const char *swordsDatName) {
Common::File f;
Common::MemFile monsters;
const int size = MONSTERS_COUNT * 61;
@@ -47,5 +49,5 @@ void writeSwordsData(CCArchive &cc, const char *swordsDatName) {
error("Invalid '%s'", swordsDatName);
monsters.write(buffer, size);
- cc.add("monsters.swd", monsters);
+ Common::File::write("monsters.swd", monsters);
}
diff --git a/devtools/create_xeen/swords.h b/devtools/create_mm/create_xeen/swords.h
similarity index 88%
rename from devtools/create_xeen/swords.h
rename to devtools/create_mm/create_xeen/swords.h
index bf18b49a314..02cc9785d7e 100644
--- a/devtools/create_xeen/swords.h
+++ b/devtools/create_mm/create_xeen/swords.h
@@ -22,9 +22,6 @@
#ifndef SWORDS_H
#define SWORDS_H
-#include "common/scummsys.h"
-#include "cc.h"
-
-extern void writeSwordsData(CCArchive &cc, const char *swordsDatName);
+extern void writeSwordsData(const char *swordsDatName);
#endif
diff --git a/devtools/create_mm/files/xeen/CONSTANTS_26 b/devtools/create_mm/files/xeen/CONSTANTS_26
new file mode 100644
index 00000000000..b5e1beb455b
Binary files /dev/null and b/devtools/create_mm/files/xeen/CONSTANTS_26 differ
diff --git a/devtools/create_mm/files/xeen/CONSTANTS_4 b/devtools/create_mm/files/xeen/CONSTANTS_4
new file mode 100644
index 00000000000..7aa88816e1c
Binary files /dev/null and b/devtools/create_mm/files/xeen/CONSTANTS_4 differ
diff --git a/devtools/create_mm/files/xeen/CONSTANTS_7 b/devtools/create_mm/files/xeen/CONSTANTS_7
new file mode 100644
index 00000000000..23febc70ffe
Binary files /dev/null and b/devtools/create_mm/files/xeen/CONSTANTS_7 differ
diff --git a/devtools/create_mm/files/xeen/CONSTKEYS_26 b/devtools/create_mm/files/xeen/CONSTKEYS_26
new file mode 100644
index 00000000000..b8cd3cdd836
Binary files /dev/null and b/devtools/create_mm/files/xeen/CONSTKEYS_26 differ
diff --git a/devtools/create_mm/files/xeen/CONSTKEYS_4 b/devtools/create_mm/files/xeen/CONSTKEYS_4
new file mode 100644
index 00000000000..af1deb36c6d
Binary files /dev/null and b/devtools/create_mm/files/xeen/CONSTKEYS_4 differ
diff --git a/devtools/create_mm/files/xeen/CONSTKEYS_7 b/devtools/create_mm/files/xeen/CONSTKEYS_7
new file mode 100644
index 00000000000..ef20f7df615
Binary files /dev/null and b/devtools/create_mm/files/xeen/CONSTKEYS_7 differ
diff --git a/devtools/create_mm/files/xeen/aazex255.hed b/devtools/create_mm/files/xeen/aazex255.hed
new file mode 100644
index 00000000000..a64a5a93fb4
Binary files /dev/null and b/devtools/create_mm/files/xeen/aazex255.hed differ
diff --git a/devtools/create_mm/files/xeen/aazex255.txt b/devtools/create_mm/files/xeen/aazex255.txt
new file mode 100644
index 00000000000..a72d7612342
Binary files /dev/null and b/devtools/create_mm/files/xeen/aazex255.txt differ
diff --git a/devtools/create_mm/files/xeen/animinfo.cld b/devtools/create_mm/files/xeen/animinfo.cld
new file mode 100644
index 00000000000..6b6f53b9f8d
Binary files /dev/null and b/devtools/create_mm/files/xeen/animinfo.cld differ
diff --git a/devtools/create_mm/files/xeen/mae.cld b/devtools/create_mm/files/xeen/mae.cld
new file mode 100644
index 00000000000..c668795383e
Binary files /dev/null and b/devtools/create_mm/files/xeen/mae.cld differ
diff --git a/devtools/create_mm/files/xeen/mapnames.cld b/devtools/create_mm/files/xeen/mapnames.cld
new file mode 100644
index 00000000000..d2e925f602f
Binary files /dev/null and b/devtools/create_mm/files/xeen/mapnames.cld differ
diff --git a/devtools/create_mm/files/xeen/mazex255.dat b/devtools/create_mm/files/xeen/mazex255.dat
new file mode 100644
index 00000000000..9abcaa2e74f
Binary files /dev/null and b/devtools/create_mm/files/xeen/mazex255.dat differ
diff --git a/devtools/create_mm/files/xeen/mazex255.evt b/devtools/create_mm/files/xeen/mazex255.evt
new file mode 100644
index 00000000000..ab446030dbe
Binary files /dev/null and b/devtools/create_mm/files/xeen/mazex255.evt differ
diff --git a/devtools/create_mm/files/xeen/mazex255.mob b/devtools/create_mm/files/xeen/mazex255.mob
new file mode 100644
index 00000000000..94e7fb0cdfb
Binary files /dev/null and b/devtools/create_mm/files/xeen/mazex255.mob differ
diff --git a/devtools/create_mm/files/xeen/monsters.cld b/devtools/create_mm/files/xeen/monsters.cld
new file mode 100644
index 00000000000..42fcd9443cf
Binary files /dev/null and b/devtools/create_mm/files/xeen/monsters.cld differ
diff --git a/devtools/create_mm/files/xeen/monsters.swd b/devtools/create_mm/files/xeen/monsters.swd
new file mode 100644
index 00000000000..42070641084
Binary files /dev/null and b/devtools/create_mm/files/xeen/monsters.swd differ
diff --git a/devtools/create_mm/files/xeen/spells.cld b/devtools/create_mm/files/xeen/spells.cld
new file mode 100644
index 00000000000..2c882040219
Binary files /dev/null and b/devtools/create_mm/files/xeen/spells.cld differ
diff --git a/devtools/create_mm/files/xeen/version.txt b/devtools/create_mm/files/xeen/version.txt
new file mode 100644
index 00000000000..d3827e75a5c
--- /dev/null
+++ b/devtools/create_mm/files/xeen/version.txt
@@ -0,0 +1 @@
+1.0
diff --git a/devtools/create_mm/files/xeen/wallpics.cld b/devtools/create_mm/files/xeen/wallpics.cld
new file mode 100644
index 00000000000..a0e8b93d208
--- /dev/null
+++ b/devtools/create_mm/files/xeen/wallpics.cld
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/devtools/create_mm/files/xeen/xeenmirr.ext b/devtools/create_mm/files/xeen/xeenmirr.ext
new file mode 100644
index 00000000000..85086d70cb2
Binary files /dev/null and b/devtools/create_mm/files/xeen/xeenmirr.ext differ
diff --git a/devtools/create_mm/files/xeen/xeenmirr.txt b/devtools/create_mm/files/xeen/xeenmirr.txt
new file mode 100644
index 00000000000..7d3bcf046b7
Binary files /dev/null and b/devtools/create_mm/files/xeen/xeenmirr.txt differ
diff --git a/devtools/create_mm/files/xeen/xeenx255.txt b/devtools/create_mm/files/xeen/xeenx255.txt
new file mode 100644
index 00000000000..b06ea7320d3
Binary files /dev/null and b/devtools/create_mm/files/xeen/xeenx255.txt differ
diff --git a/devtools/create_xeen/str.cpp b/devtools/create_xeen/str.cpp
deleted file mode 100644
index a2a4aa5fd93..00000000000
--- a/devtools/create_xeen/str.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#define SCUMMVM_UTIL
-#include "../../common/str-base.cpp"
-#include "../../common/str.cpp"
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 31f0530a69e..d6ba6f7ffc2 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/mm
MODULE_OBJS := \
metaengine.o \
+ utils/engine_data.o \
mm1/events.o \
mm1/mm1.o \
mm1/gfx/gfx.o \
diff --git a/engines/mm/utils/engine_data.cpp b/engines/mm/utils/engine_data.cpp
new file mode 100644
index 00000000000..8626d997388
--- /dev/null
+++ b/engines/mm/utils/engine_data.cpp
@@ -0,0 +1,313 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/file.h"
+#include "common/translation.h"
+#include "common/compression/unzip.h"
+#include "mm/utils/engine_data.h"
+
+#define DATA_FILENAME "mm.dat"
+
+namespace MM {
+
+class DataArchiveMember : public Common::ArchiveMember {
+private:
+ Common::SharedPtr<Common::ArchiveMember> _member;
+ Common::String _publicFolder;
+ Common::String _innerfolder;
+public:
+ DataArchiveMember(Common::SharedPtr<Common::ArchiveMember> member,
+ const Common::String &subfolder, const Common::String &publicFolder) :
+ _member(member), _publicFolder(publicFolder), _innerfolder(subfolder) {
+ }
+ ~DataArchiveMember() override {
+ }
+ Common::SeekableReadStream *createReadStream() const override {
+ return _member->createReadStream();
+ }
+ Common::String getName() const override {
+ Common::String name = _member->getName();
+ assert(name.hasPrefixIgnoreCase(_innerfolder));
+ return _publicFolder + Common::String(name.c_str() + _innerfolder.size());
+ }
+ Common::U32String getDisplayName() const override {
+ return _member->getDisplayName();
+ }
+};
+
+/**
+ * The data archive class encapsulates access to a specific subfolder
+ * for the game within the engine data zip file as a generic "data" folder
+ */
+class DataArchive : public Common::Archive {
+private:
+ Common::Archive *_zip;
+ Common::String _publicFolder;
+ Common::String _innerfolder;
+
+ Common::String innerToPublic(const Common::String &filename) const {
+ assert(filename.hasPrefixIgnoreCase(_publicFolder));
+ return _innerfolder + Common::String(filename.c_str() + _publicFolder.size());
+ }
+public:
+ DataArchive(Common::Archive *zip, const Common::String &subfolder, bool useDataPrefix) :
+ _zip(zip), _publicFolder(useDataPrefix ? "data/" : ""), _innerfolder(subfolder + "/") {
+ }
+ ~DataArchive() override {
+ delete _zip;
+ }
+
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ bool hasFile(const Common::Path &path) const override;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ int listMembers(Common::ArchiveMemberList &list) const override;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ const Common::ArchiveMemberPtr getMember(const Common::Path &path)
+ const override;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ Common::SeekableReadStream *createReadStreamForMember(
+ const Common::Path &path) const override;
+};
+
+#ifndef RELEASE_BUILD
+
+/**
+ * The data archive proxy class is used for debugging purposes to access engine data
+ * files when the create_mm folder is in the search path. It will allow for
+ * local mucking around with the data files and committing changes without having to
+ * recreate the data file every time a change is made. mm.dat then just has
+ * to be recreated prior to a release or when the changes are completed and stable
+ */
+class DataArchiveProxy : public Common::Archive {
+ friend class DataArchive;
+private:
+ Common::FSNode _folder;
+ const Common::String _publicFolder;
+
+ /**
+ * Gets a file node from the passed filename
+ */
+ Common::FSNode getNode(const Common::String &name) const;
+public:
+ DataArchiveProxy(const Common::FSNode &folder, bool useDataPrefix) :
+ _folder(folder), _publicFolder(useDataPrefix ? "data/" : "") {}
+ ~DataArchiveProxy() override {}
+
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ bool hasFile(const Common::Path &path) const override {
+ Common::String name = path.toString();
+ return name.hasPrefixIgnoreCase(_publicFolder) && getNode(name).exists();
+ }
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ int listMembers(Common::ArchiveMemberList &list) const override {
+ return 0;
+ }
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ const Common::ArchiveMemberPtr getMember(const Common::Path &path)
+ const override;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ Common::SeekableReadStream *createReadStreamForMember(
+ const Common::Path &path) const override;
+};
+
+#endif
+
+bool DataArchive::hasFile(const Common::Path &path) const {
+ Common::String name = path.toString();
+ if (!name.hasPrefixIgnoreCase(_publicFolder))
+ return false;
+
+ Common::String realFilename = innerToPublic(name);
+ return _zip->hasFile(realFilename);
+}
+
+int DataArchive::listMembers(Common::ArchiveMemberList &list) const {
+ Common::ArchiveMemberList innerList;
+ int result = _zip->listMembers(innerList);
+
+ // Modify the results to change the filename
+ for (Common::ArchiveMemberList::iterator it = innerList.begin();
+ it != innerList.end(); ++it) {
+ Common::ArchiveMemberPtr member = Common::ArchiveMemberPtr(
+ new DataArchiveMember(*it, _innerfolder, _publicFolder));
+ list.push_back(member);
+ }
+
+ return result;
+}
+
+const Common::ArchiveMemberPtr DataArchive::getMember(const Common::Path &path) const {
+ Common::String name = path.toString();
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *DataArchive::createReadStreamForMember(const Common::Path &path) const {
+ Common::String name = path.toString();
+ if (hasFile(name)) {
+ Common::String filename = innerToPublic(name);
+ return _zip->createReadStreamForMember(filename);
+ }
+
+ return nullptr;
+}
+
+/*-------------------------------------------------------------------*/
+
+#ifndef RELEASE_BUILD
+
+const Common::ArchiveMemberPtr DataArchiveProxy::getMember(const Common::Path &path) const {
+ Common::String name = path.toString();
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *DataArchiveProxy::createReadStreamForMember(const Common::Path &path) const {
+ Common::String name = path.toString();
+ if (hasFile(name))
+ return getNode(name).createReadStream();
+
+ return nullptr;
+}
+
+Common::FSNode DataArchiveProxy::getNode(const Common::String &name) const {
+ Common::String remainingName = name.substr(_publicFolder.size());
+ Common::FSNode node = _folder;
+ size_t pos;
+
+ while ((pos = remainingName.findFirstOf('/')) != Common::String::npos) {
+ node = node.getChild(remainingName.substr(0, pos));
+ if (!node.exists())
+ return node;
+
+ remainingName = remainingName.substr(pos + 1);
+ }
+
+ if (!remainingName.empty())
+ node = node.getChild(remainingName);
+
+ return node;
+}
+
+#endif
+
+/*-------------------------------------------------------------------*/
+
+bool load_engine_data(const Common::String &subfolder, int reqMajorVersion,
+ int reqMinorVersion, Common::U32String &errorMsg, bool useDataPrefix) {
+ Common::Archive *dataArchive = nullptr;
+ Common::File f;
+
+#ifndef RELEASE_BUILD
+ Common::FSNode folder;
+ if (ConfMan.hasKey("extrapath")) {
+ if ((folder = Common::FSNode(ConfMan.get("extrapath"))).exists()
+ && (folder = folder.getChild("files")).exists()
+ && (folder = folder.getChild(subfolder)).exists()) {
+ f.open(folder.getChild("version.txt"));
+ }
+ }
+
+#endif
+ if (!f.isOpen()) {
+ if (!Common::File::exists(DATA_FILENAME) ||
+ (dataArchive = Common::makeZipArchive(DATA_FILENAME)) == 0 ||
+ !f.open(Common::String::format("%s/version.txt", subfolder.c_str()), *dataArchive)) {
+ delete dataArchive;
+ errorMsg = Common::U32String::format(_("Could not locate engine data %s"), DATA_FILENAME);
+ return false;
+ }
+ }
+
+ // Validate the version
+ char buffer[5];
+ f.read(buffer, 4);
+ buffer[4] = '\0';
+
+ int major = 0, minor = 0;
+ if (buffer[1] == '.') {
+ major = buffer[0] - '0';
+ minor = atoi(&buffer[2]);
+ }
+
+ if (major != reqMajorVersion || minor != reqMinorVersion) {
+ delete dataArchive;
+ errorMsg = Common::U32String::format(_("Out of date engine data. Expected %d.%d, but got version %d.%d"),
+ reqMajorVersion, reqMinorVersion, major, minor);
+ return false;
+ }
+
+ // It was all validated correctly
+ Common::Archive *archive;
+#ifndef RELEASE_BUILD
+ if (!dataArchive)
+ archive = new DataArchiveProxy(folder, useDataPrefix);
+ else
+#endif
+ archive = new DataArchive(dataArchive, subfolder, useDataPrefix);
+
+ SearchMan.add("data", archive);
+ return true;
+}
+
+} // namespace MM
diff --git a/engines/mm/utils/engine_data.h b/engines/mm/utils/engine_data.h
new file mode 100644
index 00000000000..83e2972897b
--- /dev/null
+++ b/engines/mm/utils/engine_data.h
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Provides convenient access to a subfolder within the engine data
+ * zip file for the mm engine, by mapping it into ScummVM's filesystem.
+ * You simply specify the subfolder for your game, and the contents of
+ * that folder will be mapped in so you can calling Common::File::open
+ * with their filenames directly like file1.png or data/file1.png,
+ * depending on the useDataPrefix flag passed in the function below.
+ *
+ * The mm engine has an associated data zip file whose contents are
+ * in /devtools/create_mm/files/. Each game has their own subfolder
+ * within it, and as part of the release process, this folder will be
+ * zipped up as a file 'mm.dat', and included with ScummVM releases.
+ *
+ * For development purposes, if you go the Edit Game dialog for a
+ * game in the ScummVM launcher, and set the extra path to
+ * /devtools/create_mm, the engine will access the files directly
+ * without requiring you to keep regenerating mm.dat.
+ *
+ */
+
+#ifndef MM_UTILS_ENGINE_DATA_H
+#define MM_UTILS_ENGINE_DATA_H
+
+#include "common/str.h"
+
+namespace MM {
+
+/**
+ * Loads the engine data file and maps it into the filessystem
+ * so that the files within it can be opened as normal files.
+ * @param subfolder Subfolder in the engine data for the game
+ * @param reqMajorVersion Required major version number the
+ * folder contents need to be (as specified in version.txt)
+ * @param reqMinorVersion Required minor version
+ * @param errorMsg If an error occurs, contains a description
+ * @param useDataPrefix If true, the subfolder gets mapped into
+ * ScummVM as a 'data' subfolder, to differentiate them from files
+ * directly in the game folder. If false, the default, then filenames\
+ */
+extern bool load_engine_data(const Common::String &subfolder,
+ int reqMajorVersion, int reqMinorVersion,
+ Common::U32String &errorMsg, bool useDataPrefix = false);
+
+} // namespace MM
+
+#endif
diff --git a/engines/mm/xeen/files.cpp b/engines/mm/xeen/files.cpp
index 563979dae11..478b7e70bf4 100644
--- a/engines/mm/xeen/files.cpp
+++ b/engines/mm/xeen/files.cpp
@@ -27,6 +27,7 @@
#include "mm/xeen/xeen.h"
#include "mm/xeen/files.h"
#include "mm/xeen/saves.h"
+#include "mm/utils/engine_data.h"
namespace MM {
namespace Xeen {
@@ -266,21 +267,13 @@ bool FileManager::setup() {
File::_darkCc : File::_xeenCc;
assert(File::_currentArchive);
- // Ensure the custom CC archive is present
- File f;
- if (!f.exists("xeen.ccs")) {
- GUIErrorMessage("Could not find xeen.ccs data file");
+ // Set up the engine data file
+ Common::U32String errMsg;
+ if (!MM::load_engine_data("xeen", 1, 0, errMsg)) {
+ GUIErrorMessage(errMsg);
return false;
}
- // Verify the version of the CC is correct
- CCArchive *dataCc = new CCArchive("xeen.ccs", "data", true);
- if (!f.open("VERSION", *dataCc) || f.readUint32LE() != 5) {
- GUIErrorMessage("xeen.ccs is out of date");
- return false;
- }
- SearchMan.add("data", dataCc);
-
return true;
}
diff --git a/engines/mm/xeen/resources.h b/engines/mm/xeen/resources.h
index 3409d3c7a3a..745cb096a59 100644
--- a/engines/mm/xeen/resources.h
+++ b/engines/mm/xeen/resources.h
@@ -48,7 +48,9 @@ class Resources {
char *_buffer;
char *_buffStart;
public:
- ResFile(const char *type, char *buffer, int num) : File(type + Common::String::format("%i", num)), _buffer(buffer), _buffStart(buffer) {
+ ResFile(const char *type, char *buffer, int num) :
+ File(Common::String::format("%s%i", type, num)),
+ _buffer(buffer), _buffStart(buffer) {
}
void syncString(const char *&str) {
@@ -107,7 +109,8 @@ private:
char _buffer[STRING_BUFFER_SIZE];
private:
/**
- * Loads all the constants data stored in the xeen.ccs archive shipped with ScummVM
+ * Loads all the constants data stored in the engine data
+ * shipped with ScummVM
*/
void loadData();
public:
@@ -117,7 +120,7 @@ public:
Common::StringArray _cloudsMapNames; // Clouds of Xeen map names
const char **ITEM_NAMES[4];
- // Data loaded from xeen.ccs
+ // Data loaded from the engine data
const char *CLOUDS_CREDITS;
const char *DARK_SIDE_CREDITS;
const char *SWORDS_CREDITS1;
Commit: fe3d35a58cab7010bf864fbde37bcf2261daf0e5
https://github.com/scummvm/scummvm/commit/fe3d35a58cab7010bf864fbde37bcf2261daf0e5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: Created YAML file reader for representing string constants
Changed paths:
A devtools/create_mm/files/mm1/strings_en.yml
A devtools/create_mm/files/mm1/version.txt
A engines/mm/mm1/globals.cpp
A engines/mm/mm1/globals.h
A engines/mm/utils/strings_data.cpp
A engines/mm/utils/strings_data.h
engines/mm/POTFILES
engines/mm/mm1/mm1.cpp
engines/mm/mm1/mm1.h
engines/mm/module.mk
engines/mm/utils/engine_data.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
new file mode 100644
index 00000000000..5f209223108
--- /dev/null
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -0,0 +1,14 @@
+dialogs:
+ ready:
+ 1: " ARE YOU READY? "
+ 2: "THEN PRESS ENTER!"
+ main_menu:
+ title1: "MIGHT AND MAGIC"
+ title2: "SECRET OF THE INNER SANCTUM"
+ title3: "OPTIONS"
+ title4: "-------"
+ option1: "'C'.......CREATE NEW CHARACTERS"
+ option2: "'V'.......VIEW ALL CHARACTERS"
+ option3: "'#'.......GO TO TOWN"
+ copyright1: "COPR. 1986,1987-JON VAN CANEGHEM"
+ copyright2: "ALL RIGHTS RESERVED"
diff --git a/devtools/create_mm/files/mm1/version.txt b/devtools/create_mm/files/mm1/version.txt
new file mode 100644
index 00000000000..d3827e75a5c
--- /dev/null
+++ b/devtools/create_mm/files/mm1/version.txt
@@ -0,0 +1 @@
+1.0
diff --git a/engines/mm/POTFILES b/engines/mm/POTFILES
index 5add393836d..3aaca66720f 100644
--- a/engines/mm/POTFILES
+++ b/engines/mm/POTFILES
@@ -1,2 +1,3 @@
engines/mm/detection.cpp
+engines/mm/utils/engine_data.cpp
engines/mm/xeen/saves.cpp
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
new file mode 100644
index 00000000000..52883033fcf
--- /dev/null
+++ b/engines/mm/mm1/globals.cpp
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "engines/engine.h"
+#include "mm/mm1/globals.h"
+#include "mm/utils/engine_data.h"
+
+namespace MM {
+namespace MM1 {
+
+bool Globals::load() {
+ // Initialise engine data for the game
+ Common::U32String errMsg;
+ if (!load_engine_data("mm1", 1, 0, errMsg)) {
+ GUIErrorMessage(errMsg);
+ return false;
+ }
+
+ if (!_strings.load("strings_en.yml"))
+ return false;
+
+ return true;
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
new file mode 100644
index 00000000000..9309bc8cd71
--- /dev/null
+++ b/engines/mm/mm1/globals.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GLOBALS_H
+#define MM1_GLOBALS_H
+
+#include "mm/utils/strings_data.h"
+
+namespace MM {
+namespace MM1 {
+
+class Globals {
+public:
+ StringsData _strings;
+public:
+ Globals() {}
+
+ /**
+ * Loads data for the globals
+ */
+ bool load();
+};
+
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index ff84f30fb64..ae2cf51ec09 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -43,10 +43,16 @@ MM1Engine::~MM1Engine() {
}
Common::Error MM1Engine::run() {
+ // Initialize graphics mode
initGraphics(320, 200);
Gfx::GFX::setEgaPalette(0);
- Views::TitleView screenView(this);
+ // Load globals
+ if (!_globals.load())
+ return Common::kNoError;
+
+ // Run the game
+ Views::TitleView screenView(this);
runGame();
return Common::kNoError;
}
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index af1455d54e0..4bd584ff39b 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -26,6 +26,7 @@
#include "mm/detection.h"
#include "mm/mm.h"
#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
/**
* This is the Might and Magic I engine
@@ -41,6 +42,8 @@ private:
// Engine APIs
Common::Error run() override;
+public:
+ Globals _globals;
public:
MM1Engine(OSystem *syst, const MightAndMagicGameDescription *gameDesc);
~MM1Engine() override;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index d6ba6f7ffc2..fb976fde5f6 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -3,7 +3,9 @@ MODULE := engines/mm
MODULE_OBJS := \
metaengine.o \
utils/engine_data.o \
+ utils/strings_data.o \
mm1/events.o \
+ mm1/globals.o \
mm1/mm1.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
diff --git a/engines/mm/utils/engine_data.h b/engines/mm/utils/engine_data.h
index 83e2972897b..82ae544186f 100644
--- a/engines/mm/utils/engine_data.h
+++ b/engines/mm/utils/engine_data.h
@@ -32,7 +32,7 @@
* within it, and as part of the release process, this folder will be
* zipped up as a file 'mm.dat', and included with ScummVM releases.
*
- * For development purposes, if you go the Edit Game dialog for a
+ * For development purposes, if you go the Game Options dialog for a
* game in the ScummVM launcher, and set the extra path to
* /devtools/create_mm, the engine will access the files directly
* without requiring you to keep regenerating mm.dat.
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
new file mode 100644
index 00000000000..63613a1b7d7
--- /dev/null
+++ b/engines/mm/utils/strings_data.cpp
@@ -0,0 +1,98 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/array.h"
+#include "common/file.h"
+#include "mm/utils/strings_data.h"
+
+namespace MM {
+
+bool StringsData::load(const Common::String &filename) {
+ Common::File f;
+ Common::Array<Common::String> prefixKeys;
+ Common::String key, value, fullKey;
+ size_t p;
+
+ if (!f.open(filename))
+ return false;
+
+ while (!f.eos()) {
+ // Get the next line
+ Common::String line = f.readLine();
+
+ // Check for blank or commen tlines
+ Common::String lineTrimmed = line;
+ lineTrimmed.trim();
+ if (lineTrimmed.empty() || lineTrimmed.hasPrefix("#"))
+ continue;
+
+ // Count number of tabs for identation amount
+ size_t numTabs = 0;
+ while (line.hasPrefix("\t")) {
+ line.deleteChar(0);
+ ++numTabs;
+ }
+
+ // Split key and value if present
+ p = line.findFirstOf(":");
+ if (p == Common::String::npos)
+ error("Line encountered without colon");
+
+ key = Common::String(line.c_str(), line.c_str() + p);
+ value = Common::String(line.c_str() + p + 1);
+ key.trim();
+ value.trim();
+
+ // Handle quoted string values
+ if (value.hasPrefix("\"") && value.hasSuffix("\"")) {
+ value.deleteChar(0);
+ value.deleteLastChar();
+ }
+
+ // Handle the entries
+ if (numTabs == prefixKeys.size()) {
+ // Do nothing
+ } else if (numTabs < prefixKeys.size()) {
+ // Drop off prefixes to the desired indentation
+ prefixKeys.resize(numTabs);
+ } else {
+ error("Incorrect indentation");
+ }
+
+ if (value.empty()) {
+ prefixKeys.push_back(key);
+ } else {
+ // Form a key from the prefix and current key
+ fullKey = "";
+ for (size_t i = 0; i < prefixKeys.size(); ++i) {
+ fullKey += prefixKeys[i];
+ fullKey += ".";
+ }
+
+ fullKey = fullKey + key;
+ (*this)[fullKey] = value;
+ }
+ }
+
+ return true;
+}
+
+} // namespace MM
diff --git a/engines/mm/utils/strings_data.h b/engines/mm/utils/strings_data.h
new file mode 100644
index 00000000000..af0eb7592c9
--- /dev/null
+++ b/engines/mm/utils/strings_data.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_UTILS_STRINGS_DATA_H
+#define MM_UTILS_STRINGS_DATA_H
+
+#include "common/hash-str.h"
+
+namespace MM {
+
+class StringsData : public Common::StringMap {
+public:
+ StringsData() : Common::StringMap() {}
+
+ /**
+ * Loads the data
+ */
+ bool load(const Common::String &filename);
+};
+
+} // namespace MM
+
+#endif
Commit: 027d7a5102a2e2f718256656572ef35c1558feae
https://github.com/scummvm/scummvm/commit/027d7a5102a2e2f718256656572ef35c1558feae
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: Remove old xeen.ccs, change references to be mm.dat
Changed paths:
R dists/engine-data/xeen.ccs
Makefile.common
devtools/create_project/xcode.cpp
dists/engine-data/README
dists/irix/scummvm.idb
dists/scummvm.rc
diff --git a/Makefile.common b/Makefile.common
index d240c8f1a31..a112975f697 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -465,7 +465,7 @@ ifdef ENABLE_WINTERMUTE
DIST_FILES_ENGINEDATA+=wintermute.zip
endif
ifdef ENABLE_XEEN
-DIST_FILES_ENGINEDATA+=xeen.ccs
+DIST_FILES_ENGINEDATA+=mm.dat
endif
ifdef ENABLE_FREESCAPE
DIST_FILES_ENGINEDATA+=freescape.dat
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index 358903acf4a..f6c52fb8f25 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -850,6 +850,7 @@ XcodeProvider::ValueList& XcodeProvider::getResourceFiles(const BuildSetup &setu
files.push_back("dists/engine-data/monkey4-patch.m4b");
files.push_back("dists/engine-data/grim-patch.lab");
files.push_back("dists/engine-data/macventure.dat");
+ files.push_back("dists/engine-data/mm.dat");
files.push_back("dists/engine-data/mort.dat");
files.push_back("dists/engine-data/neverhood.dat");
files.push_back("dists/engine-data/queen.tbl");
@@ -861,7 +862,6 @@ XcodeProvider::ValueList& XcodeProvider::getResourceFiles(const BuildSetup &setu
files.push_back("dists/engine-data/toon.dat");
files.push_back("dists/engine-data/ultima.dat");
files.push_back("dists/engine-data/wintermute.zip");
- files.push_back("dists/engine-data/xeen.ccs");
files.push_back("dists/ios7/LaunchScreen_ios.storyboard");
files.push_back("dists/pred.dic");
files.push_back("dists/networking/wwwroot.zip");
diff --git a/dists/engine-data/README b/dists/engine-data/README
index 9d02f2d0644..d5c02a1bf7b 100644
--- a/dists/engine-data/README
+++ b/dists/engine-data/README
@@ -88,5 +88,5 @@ This file contains scripts and game data used by Ultima engine.
wintermute.zip:
This file contains additional graphics resources used by Wintermute engine.
-xeen.ccs:
-This file contains all the various strings and figures needed for the games.
+mm.dat:
+This file contains all the various strings and data needed for the Might & Magic games.
diff --git a/dists/engine-data/xeen.ccs b/dists/engine-data/xeen.ccs
deleted file mode 100644
index 7486b952110..00000000000
Binary files a/dists/engine-data/xeen.ccs and /dev/null differ
diff --git a/dists/irix/scummvm.idb b/dists/irix/scummvm.idb
index 86800452485..9a40a63807f 100644
--- a/dists/irix/scummvm.idb
+++ b/dists/irix/scummvm.idb
@@ -39,7 +39,7 @@ f 0644 root sys usr/ScummVM/share/scummvm/toon.dat toon.dat scummvm.sw.eoe
f 0644 root sys usr/ScummVM/share/scummvm/ultima.dat ultima.dat scummvm.sw.eoe
f 0644 root sys usr/ScummVM/share/scummvm/freescape.dat freescape.dat scummvm.sw.eoe
f 0644 root sys usr/ScummVM/share/scummvm/wintermute.zip wintermute.zip scummvm.sw.eoe
-f 0644 root sys usr/ScummVM/share/scummvm/xeen.ccs xeen.ccs scummvm.sw.eoe
+f 0644 root sys usr/ScummVM/share/scummvm/mm.dat mm.dat scummvm.sw.eoe
f 0644 root sys usr/ScummVM/share/scummvm/pred.dic pred.dic scummvm.sw.eoe
f 0644 root sys usr/ScummVM/share/scummvm/scummmodern.zip scummmodern.zip scummvm.sw.eoe
f 0644 root sys usr/ScummVM/share/scummvm/scummremastered.zip scummremastered.zip scummvm.sw.eoe
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 9f3f801d0fe..c95ce636ab9 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -113,7 +113,7 @@ ultima.dat FILE "dists/engine-data/ultima.dat"
wintermute.zip FILE "dists/engine-data/wintermute.zip"
#endif
#if PLUGIN_ENABLED_STATIC(XEEN)
-xeen.ccs FILE "dists/engine-data/xeen.ccs"
+mm.dat FILE "dists/engine-data/mm.dat"
#endif
#if PLUGIN_ENABLED_STATIC(AGI)
pred.dic FILE "dists/pred.dic"
Commit: 97a0f7825d665f05c248a41491e0866ddeb5eac9
https://github.com/scummvm/scummvm/commit/97a0f7825d665f05c248a41491e0866ddeb5eac9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: MM1: Beginnings of text views
Temporarily using using one of the bundled TTF fonts. Need to
replace it with a proper font matching the DOS 8x8 (40x25) font
Changed paths:
A engines/mm/mm1/views/are_you_ready.cpp
A engines/mm/mm1/views/are_you_ready.h
A engines/mm/mm1/views/main_menu.cpp
A engines/mm/mm1/views/main_menu.h
engines/mm/mm1/gfx/gfx.cpp
engines/mm/mm1/gfx/gfx.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/gfx/gfx.cpp b/engines/mm/mm1/gfx/gfx.cpp
index 489e22a1419..bc107495991 100644
--- a/engines/mm/mm1/gfx/gfx.cpp
+++ b/engines/mm/mm1/gfx/gfx.cpp
@@ -49,6 +49,10 @@ void GFX::setEgaPalette(int palNum) {
*pDest = VGA_COLOR_TRANS(*pSrc);
g_system->getPaletteManager()->setPalette(pal, 0, 16);
+
+ uint32 c = 0xffffffff;
+ for (int i = 1; i < 256; ++i)
+ g_system->getPaletteManager()->setPalette((const byte *)&c, i, 1);
}
} // namespace Gfx
diff --git a/engines/mm/mm1/gfx/gfx.h b/engines/mm/mm1/gfx/gfx.h
index dd677fed924..b3119d3ec1f 100644
--- a/engines/mm/mm1/gfx/gfx.h
+++ b/engines/mm/mm1/gfx/gfx.h
@@ -28,6 +28,12 @@ namespace MM {
namespace MM1 {
namespace Gfx {
+#define FONT_SIZE 8
+#define TEXT_W 40
+#define TEXT_H 25
+#define SCREEN_W 320
+#define SCREEN_H 200
+
class GFX {
public:
static void setEgaPalette(int palNum);
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 52883033fcf..5029e7969dd 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -20,12 +20,24 @@
*/
#include "engines/engine.h"
+#include "graphics/fonts/ttf.h"
#include "mm/mm1/globals.h"
#include "mm/utils/engine_data.h"
namespace MM {
namespace MM1 {
+Globals *g_globals;
+
+Globals::Globals() {
+ g_globals = this;
+}
+
+Globals::~Globals() {
+ g_globals = nullptr;
+ delete _font;
+}
+
bool Globals::load() {
// Initialise engine data for the game
Common::U32String errMsg;
@@ -37,6 +49,9 @@ bool Globals::load() {
if (!_strings.load("strings_en.yml"))
return false;
+ // Load the font
+ _font = Graphics::loadTTFFontFromArchive("GoMono-Regular.ttf", 8);
+
return true;
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 9309bc8cd71..08cac003128 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -22,6 +22,7 @@
#ifndef MM1_GLOBALS_H
#define MM1_GLOBALS_H
+#include "graphics/font.h"
#include "mm/utils/strings_data.h"
namespace MM {
@@ -30,8 +31,10 @@ namespace MM1 {
class Globals {
public:
StringsData _strings;
+ Graphics::Font *_font = nullptr;
public:
- Globals() {}
+ Globals();
+ virtual ~Globals();
/**
* Loads data for the globals
@@ -39,6 +42,9 @@ public:
bool load();
};
+extern Globals *g_globals;
+
+#define STRING (g_globals->_strings)
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index ae2cf51ec09..39b77c0053b 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -26,7 +26,9 @@
#include "engines/util.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/gfx/gfx.h"
+
#include "mm/mm1/views/title_view.h"
+#include "mm/mm1/views/are_you_ready.h"
namespace MM {
namespace MM1 {
@@ -52,7 +54,9 @@ Common::Error MM1Engine::run() {
return Common::kNoError;
// Run the game
- Views::TitleView screenView(this);
+// Views::TitleView view1(this);
+ Views::AreYouReady view1(this);
+
runGame();
return Common::kNoError;
}
diff --git a/engines/mm/mm1/views/are_you_ready.cpp b/engines/mm/mm1/views/are_you_ready.cpp
new file mode 100644
index 00000000000..cad73fa9232
--- /dev/null
+++ b/engines/mm/mm1/views/are_you_ready.cpp
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/are_you_ready.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void AreYouReady::draw() {
+ drawTextBorder();
+ writeString(11, 11, STRING["dialogs.ready.1"]);
+ writeString(11, 13, STRING["dialogs.ready.2"]);
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/are_you_ready.h b/engines/mm/mm1/views/are_you_ready.h
new file mode 100644
index 00000000000..e16406c125d
--- /dev/null
+++ b/engines/mm/mm1/views/are_you_ready.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ARE_YOU_READY_H
+#define MM1_VIEWS_ARE_YOU_READY_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class AreYouReady : public TextView {
+public:
+ AreYouReady(UIElement *uiParent = nullptr) :
+ TextView(uiParent) {}
+ virtual ~AreYouReady() {}
+
+ void draw() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/main_menu.cpp b/engines/mm/mm1/views/main_menu.cpp
new file mode 100644
index 00000000000..0b73b35e9f4
--- /dev/null
+++ b/engines/mm/mm1/views/main_menu.cpp
@@ -0,0 +1,34 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/main_menu.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void MainMenu::draw() {
+ // TODO
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/main_menu.h b/engines/mm/mm1/views/main_menu.h
new file mode 100644
index 00000000000..68f6016033f
--- /dev/null
+++ b/engines/mm/mm1/views/main_menu.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAIN_MENU_H
+#define MM1_VIEWS_MAIN_MENU_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class MainMenu : public TextView {
+public:
+ MainMenu(UIElement *uiParent = nullptr) :
+ TextView(uiParent) {
+ }
+ virtual ~MainMenu() {
+ }
+
+ void draw() override;
+};
+
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index f9b60be0092..3b2fd856558 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -19,12 +19,48 @@
*
*/
+#include "mm/mm1/globals.h"
+#include "mm/mm1/gfx/gfx.h"
#include "mm/mm1/views/text_view.h"
namespace MM {
namespace MM1 {
namespace Views {
+void TextView::writeChar(int x, int y, char c) {
+ g_globals->_font->drawChar(getScreen(), c,
+ x * FONT_SIZE, y * FONT_SIZE, 0xff);
+}
+
+void TextView::writeString(int x, int y, const Common::String &str) {
+ for (const char *s = str.c_str(); *s; ++s, ++x)
+ writeChar(x, y, *s);
+}
+
+void TextView::drawTextBorder() {
+ Graphics::ManagedSurface *scr = getScreen();
+ scr->clear();
+
+ // Draw boxes in the four corners
+ scr->fillRect(Common::Rect(0, 0, FONT_SIZE * 3, FONT_SIZE * 3), 255);
+ scr->fillRect(Common::Rect(SCREEN_W - FONT_SIZE * 3, 0,
+ SCREEN_W, FONT_SIZE * 3), 255);
+ scr->fillRect(Common::Rect(0, SCREEN_H - FONT_SIZE * 3,
+ FONT_SIZE * 3, SCREEN_H), 255);
+ scr->fillRect(Common::Rect(SCREEN_W - FONT_SIZE * 3,
+ SCREEN_H - FONT_SIZE * 3, SCREEN_W, SCREEN_H), 255);
+
+ // Draw horizontal vertical lines
+ for (int x = 3; x < TEXT_W - 3; ++x) {
+ writeChar(x, 1, '-');
+ writeChar(x, TEXT_H - 2, '-');
+ }
+ for (int y = 3; y < TEXT_H - 3; ++y) {
+ writeChar(1, y, '|');
+ writeChar(TEXT_W - 2, y, '|');
+ }
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index f10b4427cea..4c9ed542d1e 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -29,6 +29,21 @@ namespace MM1 {
namespace Views {
class TextView : public UIElement {
+protected:
+ /**
+ * Draws a text border
+ */
+ void drawTextBorder();
+
+ /**
+ * Write a character
+ */
+ void writeChar(int x, int y, char c);
+
+ /**
+ * Write some text
+ */
+ void writeString(int x, int y, const Common::String &str);
public:
TextView(UIElement *uiParent = nullptr) :
UIElement(uiParent) {}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index fb976fde5f6..d6b1852ac44 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -9,6 +9,8 @@ MODULE_OBJS := \
mm1/mm1.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
+ mm1/views/are_you_ready.o \
+ mm1/views/main_menu.o \
mm1/views/title_view.o \
mm1/views/text_view.o \
xeen/worldofxeen/clouds_cutscenes.o \
Commit: 2aaceda63280773fcb67fadba51acd7e72808372
https://github.com/scummvm/scummvm/commit/2aaceda63280773fcb67fadba51acd7e72808372
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: MM1: Somewhat improve text by using GUI console font
It's not perfectly accurate to the DOS font, but it'll
do for now
Changed paths:
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 5029e7969dd..a238d2ab1a3 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -23,6 +23,7 @@
#include "graphics/fonts/ttf.h"
#include "mm/mm1/globals.h"
#include "mm/utils/engine_data.h"
+#include "graphics/fontman.h"
namespace MM {
namespace MM1 {
@@ -35,7 +36,6 @@ Globals::Globals() {
Globals::~Globals() {
g_globals = nullptr;
- delete _font;
}
bool Globals::load() {
@@ -50,7 +50,7 @@ bool Globals::load() {
return false;
// Load the font
- _font = Graphics::loadTTFFontFromArchive("GoMono-Regular.ttf", 8);
+ _font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
return true;
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 08cac003128..cfc4b66dfbc 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -31,7 +31,7 @@ namespace MM1 {
class Globals {
public:
StringsData _strings;
- Graphics::Font *_font = nullptr;
+ const Graphics::Font *_font = nullptr;
public:
Globals();
virtual ~Globals();
Commit: 3718284f6f147a033bc04b696780a01e6d55e267
https://github.com/scummvm/scummvm/commit/3718284f6f147a033bc04b696780a01e6d55e267
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: MM1: Introduced focused view display
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/gfx/gfx.cpp
engines/mm/mm1/mm1.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index eca73f08eb4..aaf55b203fe 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -65,6 +65,7 @@ public:
class Events : public UIElement {
private:
Graphics::Screen *_screen = nullptr;
+ UIElement *_focusedElement;
protected:
/**
* Process an event
@@ -79,9 +80,26 @@ public:
*/
void runGame();
+ /**
+ * Sets the focus to a new view
+ */
+ void focusElement(UIElement *ui) {
+ _focusedElement = ui;
+ }
+
Graphics::Screen *getScreen() const override {
return _screen;
}
+
+
+ void draw() override {
+ if (_focusedElement)
+ _focusedElement->draw();
+ }
+
+ bool tick() override {
+ return _focusedElement ? _focusedElement->tick() : false;
+ }
};
} // namespace MM1
diff --git a/engines/mm/mm1/gfx/gfx.cpp b/engines/mm/mm1/gfx/gfx.cpp
index bc107495991..158f6ab6145 100644
--- a/engines/mm/mm1/gfx/gfx.cpp
+++ b/engines/mm/mm1/gfx/gfx.cpp
@@ -51,8 +51,7 @@ void GFX::setEgaPalette(int palNum) {
g_system->getPaletteManager()->setPalette(pal, 0, 16);
uint32 c = 0xffffffff;
- for (int i = 1; i < 256; ++i)
- g_system->getPaletteManager()->setPalette((const byte *)&c, i, 1);
+ g_system->getPaletteManager()->setPalette((const byte *)&c, 255, 1);
}
} // namespace Gfx
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 39b77c0053b..a495ef095ca 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -54,8 +54,9 @@ Common::Error MM1Engine::run() {
return Common::kNoError;
// Run the game
-// Views::TitleView view1(this);
- Views::AreYouReady view1(this);
+ Views::TitleView view1(this);
+ Views::AreYouReady view2(this);
+ focusElement(&view2);
runGame();
return Common::kNoError;
Commit: 3a53a48989840db9149581627932fc43b208751e
https://github.com/scummvm/scummvm/commit/3a53a48989840db9149581627932fc43b208751e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:41+01:00
Commit Message:
MM: MM1: Beginnings of keyboard message dispatch
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/views/are_you_ready.cpp
engines/mm/mm1/views/are_you_ready.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 6db1e601c04..9be02259759 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -57,7 +57,7 @@ void Events::runGame() {
void Events::processEvent(Common::Event &ev) {
switch (ev.type) {
case Common::EVENT_KEYDOWN:
- keypressEvent(ev);
+ msgKeypress(KeypressMessage(ev.kbd));
break;
default:
break;
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index aaf55b203fe..0db768a03e4 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -29,6 +29,15 @@
namespace MM {
namespace MM1 {
+struct Message {
+};
+
+struct KeypressMessage : public Message, public Common::KeyState {
+ KeypressMessage() : Message() {}
+ KeypressMessage(const Common::KeyState &ks) :
+ Message(), Common::KeyState(ks) {}
+};
+
class UIElement {
protected:
UIElement *_parent;
@@ -55,11 +64,19 @@ public:
virtual bool tick();
/**
- * Handles a keypress
+ * Handles events
*/
- virtual bool keypressEvent(const Common::Event &e) {
- return false;
- }
+ #define MESSAGE(NAME) \
+ virtual bool msg##NAME(const NAME##Message &e) { \
+ for (Common::Array<UIElement *>::iterator it = _children.begin(); \
+ it != _children.end(); ++it) { \
+ if ((*it)->msg##NAME(e)) return true; \
+ } \
+ return false; \
+ }
+
+ MESSAGE(Keypress);
+ #undef MESSAGE
};
class Events : public UIElement {
@@ -100,6 +117,16 @@ public:
bool tick() override {
return _focusedElement ? _focusedElement->tick() : false;
}
+
+ /**
+ * Handles events
+ */
+ #define MESSAGE(NAME) \
+ bool msg##NAME(const NAME##Message &e) override { \
+ return (_focusedElement) ? _focusedElement->msg##NAME(e) : false; \
+ }
+ MESSAGE(Keypress);
+ #undef MESSAGE
};
} // namespace MM1
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index a495ef095ca..422fec83d80 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -29,6 +29,7 @@
#include "mm/mm1/views/title_view.h"
#include "mm/mm1/views/are_you_ready.h"
+#include "mm/mm1/views/main_menu.h"
namespace MM {
namespace MM1 {
@@ -56,6 +57,7 @@ Common::Error MM1Engine::run() {
// Run the game
Views::TitleView view1(this);
Views::AreYouReady view2(this);
+ Views::MainMenu view3(this);
focusElement(&view2);
runGame();
diff --git a/engines/mm/mm1/views/are_you_ready.cpp b/engines/mm/mm1/views/are_you_ready.cpp
index cad73fa9232..31c6606e545 100644
--- a/engines/mm/mm1/views/are_you_ready.cpp
+++ b/engines/mm/mm1/views/are_you_ready.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/globals.h"
+#include "engines/engine.h"
namespace MM {
namespace MM1 {
@@ -32,6 +33,15 @@ void AreYouReady::draw() {
writeString(11, 13, STRING["dialogs.ready.2"]);
}
+bool AreYouReady::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ GUIErrorMessage("Enter pressed");
+ return true;
+ }
+
+ return false;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/are_you_ready.h b/engines/mm/mm1/views/are_you_ready.h
index e16406c125d..523008065a0 100644
--- a/engines/mm/mm1/views/are_you_ready.h
+++ b/engines/mm/mm1/views/are_you_ready.h
@@ -35,6 +35,7 @@ public:
virtual ~AreYouReady() {}
void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace Views
Commit: e2069e2f3506bdc4bbaa48dbf798909c6721ed68
https://github.com/scummvm/scummvm/commit/e2069e2f3506bdc4bbaa48dbf798909c6721ed68
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: Only redraw views when they mark themselves as changed
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 9be02259759..f7d810ed3b7 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -46,7 +46,7 @@ void Events::runGame() {
if ((currTime = g_system->getMillis()) >= nextFrameTime) {
nextFrameTime = currTime + FRAME_DELAY;
tick();
- draw();
+ drawElements();
_screen->update();
}
}
@@ -69,9 +69,21 @@ UIElement::UIElement(UIElement *uiParent) : _parent(uiParent) {
_parent->_children.push_back(this);
}
-void UIElement::draw() {
+void UIElement::redraw() {
+ _needsRedraw = true;
+
for (size_t i = 0; i < _children.size(); ++i)
- _children[i]->draw();
+ _children[i]->redraw();
+}
+
+void UIElement::drawElements() {
+ if (_needsRedraw) {
+ draw();
+ _needsRedraw = false;
+
+ for (size_t i = 0; i < _children.size(); ++i)
+ _children[i]->drawElements();
+ }
}
bool UIElement::tick() {
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 0db768a03e4..c5e3b67e862 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -29,6 +29,8 @@
namespace MM {
namespace MM1 {
+class Events;
+
struct Message {
};
@@ -39,13 +41,31 @@ struct KeypressMessage : public Message, public Common::KeyState {
};
class UIElement {
+ friend class Events;
protected:
UIElement *_parent;
Common::Array<UIElement *> _children;
+ bool _needsRedraw = true;
+private:
+ /**
+ * Outer method for doing drawing
+ *
+ */
+ void drawElements();
public:
UIElement(UIElement *uiParent = nullptr);
virtual ~UIElement() {}
+ /**
+ * Returns true if the elements needs to be redrawn
+ */
+ bool needsRedraw() const { return _needsRedraw; }
+
+ /**
+ * Sets that the element needs to be redrawn
+ */
+ void redraw();
+
/**
* Returns the game view
*/
@@ -56,7 +76,7 @@ public:
/**
* Draws the element
*/
- virtual void draw();
+ virtual void draw() = 0;
/**
* Called for game frame ticks
@@ -109,11 +129,13 @@ public:
}
- void draw() override {
+ void drawElements() {
if (_focusedElement)
- _focusedElement->draw();
+ _focusedElement->drawElements();
}
+ void draw() override {}
+
bool tick() override {
return _focusedElement ? _focusedElement->tick() : false;
}
Commit: e64bedbde0c5fb67a531d5dc78faa11078a2ae59
https://github.com/scummvm/scummvm/commit/e64bedbde0c5fb67a531d5dc78faa11078a2ae59
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: Add name field to elements for later searches
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views/are_you_ready.cpp
engines/mm/mm1/views/are_you_ready.h
engines/mm/mm1/views/main_menu.cpp
engines/mm/mm1/views/main_menu.h
engines/mm/mm1/views/text_view.h
engines/mm/mm1/views/title_view.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index f7d810ed3b7..2a42edcf1d5 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -64,7 +64,8 @@ void Events::processEvent(Common::Event &ev) {
}
}
-UIElement::UIElement(UIElement *uiParent) : _parent(uiParent) {
+UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
+ _name(name), _parent(uiParent) {
if (_parent)
_parent->_children.push_back(this);
}
@@ -95,5 +96,19 @@ bool UIElement::tick() {
return false;
}
+UIElement *UIElement::findElement(const Common::String &name) {
+ if (_name.equalsIgnoreCase(name))
+ return this;
+
+ UIElement *result;
+ for (size_t i = 0; i < _children.size(); ++i) {
+ if ((result = _children[i]->findElement(name)) != nullptr)
+ return result;
+ }
+
+ return nullptr;
+}
+
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index c5e3b67e862..3f2e2ab6352 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -46,6 +46,7 @@ protected:
UIElement *_parent;
Common::Array<UIElement *> _children;
bool _needsRedraw = true;
+ Common::String _name;
private:
/**
* Outer method for doing drawing
@@ -53,7 +54,7 @@ private:
*/
void drawElements();
public:
- UIElement(UIElement *uiParent = nullptr);
+ UIElement(const Common::String &name, UIElement *uiParent);
virtual ~UIElement() {}
/**
@@ -83,6 +84,11 @@ public:
*/
virtual bool tick();
+ /**
+ * Find an element by name
+ */
+ virtual UIElement *findElement(const Common::String &name);
+
/**
* Handles events
*/
@@ -109,7 +115,7 @@ protected:
*/
void processEvent(Common::Event &ev);
public:
- Events() {}
+ Events() : UIElement("", nullptr) {}
virtual ~Events() {}
/**
diff --git a/engines/mm/mm1/views/are_you_ready.cpp b/engines/mm/mm1/views/are_you_ready.cpp
index 31c6606e545..78a7d4324c3 100644
--- a/engines/mm/mm1/views/are_you_ready.cpp
+++ b/engines/mm/mm1/views/are_you_ready.cpp
@@ -21,7 +21,7 @@
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/globals.h"
-#include "engines/engine.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
@@ -35,7 +35,7 @@ void AreYouReady::draw() {
bool AreYouReady::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_RETURN) {
- GUIErrorMessage("Enter pressed");
+ g_engine->focusElement(g_engine->findElement("MainMenu"));
return true;
}
diff --git a/engines/mm/mm1/views/are_you_ready.h b/engines/mm/mm1/views/are_you_ready.h
index 523008065a0..bb57d4defc9 100644
--- a/engines/mm/mm1/views/are_you_ready.h
+++ b/engines/mm/mm1/views/are_you_ready.h
@@ -31,7 +31,7 @@ namespace Views {
class AreYouReady : public TextView {
public:
AreYouReady(UIElement *uiParent = nullptr) :
- TextView(uiParent) {}
+ TextView("AreYouReady", uiParent) {}
virtual ~AreYouReady() {}
void draw() override;
diff --git a/engines/mm/mm1/views/main_menu.cpp b/engines/mm/mm1/views/main_menu.cpp
index 0b73b35e9f4..c862fc5f151 100644
--- a/engines/mm/mm1/views/main_menu.cpp
+++ b/engines/mm/mm1/views/main_menu.cpp
@@ -27,6 +27,8 @@ namespace Views {
void MainMenu::draw() {
// TODO
+ drawTextBorder();
+ writeString(10, 10, "Main menu");
}
} // namespace Views
diff --git a/engines/mm/mm1/views/main_menu.h b/engines/mm/mm1/views/main_menu.h
index 68f6016033f..e435fa7c5eb 100644
--- a/engines/mm/mm1/views/main_menu.h
+++ b/engines/mm/mm1/views/main_menu.h
@@ -31,7 +31,7 @@ namespace Views {
class MainMenu : public TextView {
public:
MainMenu(UIElement *uiParent = nullptr) :
- TextView(uiParent) {
+ TextView("MainMenu", uiParent) {
}
virtual ~MainMenu() {
}
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 4c9ed542d1e..d56605eef3f 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -45,8 +45,8 @@ protected:
*/
void writeString(int x, int y, const Common::String &str);
public:
- TextView(UIElement *uiParent = nullptr) :
- UIElement(uiParent) {}
+ TextView(const Common::String &name, UIElement *uiParent = nullptr) :
+ UIElement(name, uiParent) {}
virtual ~TextView() {}
};
diff --git a/engines/mm/mm1/views/title_view.cpp b/engines/mm/mm1/views/title_view.cpp
index 2f3abf80a3c..bfe70f46cd4 100644
--- a/engines/mm/mm1/views/title_view.cpp
+++ b/engines/mm/mm1/views/title_view.cpp
@@ -26,7 +26,7 @@ namespace MM {
namespace MM1 {
namespace Views {
-TitleView::TitleView(UIElement *uiParent) : UIElement(uiParent) {
+TitleView::TitleView(UIElement *uiParent) : UIElement("Title", uiParent) {
Gfx::ScreenDecoder decoder;
if (decoder.loadFile("screen0")) {
_surface.copyFrom(decoder.getSurface());
Commit: 92661fbd624142c7781789c77905e67ac3a54dc6
https://github.com/scummvm/scummvm/commit/92661fbd624142c7781789c77905e67ac3a54dc6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: identify views by name, allowing for easy switching views
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/views/are_you_ready.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 2a42edcf1d5..b9cb6c61c52 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -22,6 +22,7 @@
#include "common/system.h"
#include "graphics/screen.h"
#include "mm/mm1/events.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
@@ -64,6 +65,34 @@ void Events::processEvent(Common::Event &ev) {
}
}
+void Events::replaceView(UIElement *ui) {
+ if (!_views.empty()) {
+ focusedView()->msgUnfocus(UnfocusMessage());
+ _views.clear();
+ }
+
+ _views.push(ui);
+ ui->msgFocus(FocusMessage());
+}
+
+void Events::replaceView(const Common::String &name) {
+ replaceView(findView(name));
+}
+
+void Events::addView(UIElement *ui) {
+ if (!_views.empty())
+ focusedView()->msgUnfocus(UnfocusMessage());
+
+ _views.push(ui);
+ ui->msgFocus(FocusMessage());
+}
+
+void Events::addView(const Common::String &name) {
+ addView(findView(name));
+}
+
+/*-------------------------------------------------------------------*/
+
UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
_name(name), _parent(uiParent) {
if (_parent)
@@ -87,6 +116,10 @@ void UIElement::drawElements() {
}
}
+void UIElement::focus() {
+ g_engine->replaceView(this);
+}
+
bool UIElement::tick() {
for (size_t i = 0; i < _children.size(); ++i) {
if (_children[i]->tick())
@@ -96,13 +129,13 @@ bool UIElement::tick() {
return false;
}
-UIElement *UIElement::findElement(const Common::String &name) {
+UIElement *UIElement::findView(const Common::String &name) {
if (_name.equalsIgnoreCase(name))
return this;
UIElement *result;
for (size_t i = 0; i < _children.size(); ++i) {
- if ((result = _children[i]->findElement(name)) != nullptr)
+ if ((result = _children[i]->findView(name)) != nullptr)
return result;
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 3f2e2ab6352..73e0aee2762 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -24,6 +24,7 @@
#include "common/array.h"
#include "common/events.h"
+#include "common/stack.h"
#include "graphics/screen.h"
namespace MM {
@@ -34,6 +35,9 @@ class Events;
struct Message {
};
+struct FocusMessage : public Message {};
+struct UnfocusMessage : public Message {};
+
struct KeypressMessage : public Message, public Common::KeyState {
KeypressMessage() : Message() {}
KeypressMessage(const Common::KeyState &ks) :
@@ -67,6 +71,11 @@ public:
*/
void redraw();
+ /**
+ * Focuses the element as the current view
+ */
+ void focus();
+
/**
* Returns the game view
*/
@@ -85,9 +94,9 @@ public:
virtual bool tick();
/**
- * Find an element by name
+ * Find a view by name
*/
- virtual UIElement *findElement(const Common::String &name);
+ virtual UIElement *findView(const Common::String &name);
/**
* Handles events
@@ -101,6 +110,8 @@ public:
return false; \
}
+ MESSAGE(Focus);
+ MESSAGE(Unfocus);
MESSAGE(Keypress);
#undef MESSAGE
};
@@ -108,7 +119,14 @@ public:
class Events : public UIElement {
private:
Graphics::Screen *_screen = nullptr;
- UIElement *_focusedElement;
+ Common::Stack<UIElement *> _views;
+private:
+ /**
+ * Returns the currently focused view, if any
+ */
+ UIElement *focusedView() const {
+ return _views.empty() ? nullptr : _views.top();
+ }
protected:
/**
* Process an event
@@ -126,24 +144,28 @@ public:
/**
* Sets the focus to a new view
*/
- void focusElement(UIElement *ui) {
- _focusedElement = ui;
- }
+ void replaceView(UIElement *ui);
+ void replaceView(const Common::String &name);
+
+ /**
+ * Adds a focused view to the view stack without replacing current one
+ */
+ void addView(UIElement *ui);
+ void addView(const Common::String &name);
Graphics::Screen *getScreen() const override {
return _screen;
}
-
void drawElements() {
- if (_focusedElement)
- _focusedElement->drawElements();
+ if (!_views.empty())
+ focusedView()->drawElements();
}
void draw() override {}
bool tick() override {
- return _focusedElement ? _focusedElement->tick() : false;
+ return !_views.empty() ? focusedView()->tick() : false;
}
/**
@@ -151,8 +173,10 @@ public:
*/
#define MESSAGE(NAME) \
bool msg##NAME(const NAME##Message &e) override { \
- return (_focusedElement) ? _focusedElement->msg##NAME(e) : false; \
+ return !_views.empty() ? focusedView()->msg##NAME(e) : false; \
}
+ MESSAGE(Focus);
+ MESSAGE(Unfocus);
MESSAGE(Keypress);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 422fec83d80..031a31ed1fe 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -58,7 +58,7 @@ Common::Error MM1Engine::run() {
Views::TitleView view1(this);
Views::AreYouReady view2(this);
Views::MainMenu view3(this);
- focusElement(&view2);
+ addView("AreYouReady");
runGame();
return Common::kNoError;
diff --git a/engines/mm/mm1/views/are_you_ready.cpp b/engines/mm/mm1/views/are_you_ready.cpp
index 78a7d4324c3..e41ad1c6164 100644
--- a/engines/mm/mm1/views/are_you_ready.cpp
+++ b/engines/mm/mm1/views/are_you_ready.cpp
@@ -35,7 +35,7 @@ void AreYouReady::draw() {
bool AreYouReady::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_RETURN) {
- g_engine->focusElement(g_engine->findElement("MainMenu"));
+ g_engine->replaceView("MainMenu");
return true;
}
Commit: 595958e82f35634c6cc569a4bc7dbdf754024c2c
https://github.com/scummvm/scummvm/commit/595958e82f35634c6cc569a4bc7dbdf754024c2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: Create Dialogs class as a container for all the dialogs
Changed paths:
A engines/mm/mm1/views/dialogs.cpp
A engines/mm/mm1/views/dialogs.h
engines/mm/mm1/events.cpp
engines/mm/mm1/mm1.cpp
engines/mm/mm1/views/main_menu.cpp
engines/mm/mm1/views/main_menu.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index b9cb6c61c52..ac9097854a3 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -23,6 +23,7 @@
#include "graphics/screen.h"
#include "mm/mm1/events.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/views/dialogs.h"
namespace MM {
namespace MM1 {
@@ -31,6 +32,11 @@ namespace MM1 {
#define FRAME_DELAY (1000 / FRAME_RATE)
void Events::runGame() {
+ Views::Dialogs dialogsContainer; // Load up all the dialogs
+
+ // Run the game
+ addView("AreYouReady");
+
uint currTime, nextFrameTime = 0;
_screen = new Graphics::Screen();
@@ -66,6 +72,7 @@ void Events::processEvent(Common::Event &ev) {
}
void Events::replaceView(UIElement *ui) {
+ assert(ui);
if (!_views.empty()) {
focusedView()->msgUnfocus(UnfocusMessage());
_views.clear();
@@ -80,6 +87,7 @@ void Events::replaceView(const Common::String &name) {
}
void Events::addView(UIElement *ui) {
+ assert(ui);
if (!_views.empty())
focusedView()->msgUnfocus(UnfocusMessage());
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 031a31ed1fe..380df327e14 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -27,10 +27,6 @@
#include "mm/mm1/mm1.h"
#include "mm/mm1/gfx/gfx.h"
-#include "mm/mm1/views/title_view.h"
-#include "mm/mm1/views/are_you_ready.h"
-#include "mm/mm1/views/main_menu.h"
-
namespace MM {
namespace MM1 {
@@ -54,12 +50,6 @@ Common::Error MM1Engine::run() {
if (!_globals.load())
return Common::kNoError;
- // Run the game
- Views::TitleView view1(this);
- Views::AreYouReady view2(this);
- Views::MainMenu view3(this);
- addView("AreYouReady");
-
runGame();
return Common::kNoError;
}
diff --git a/engines/mm/mm1/views/dialogs.cpp b/engines/mm/mm1/views/dialogs.cpp
new file mode 100644
index 00000000000..b7bfec56e1d
--- /dev/null
+++ b/engines/mm/mm1/views/dialogs.cpp
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/dialogs.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Dialogs::Dialogs() :
+ _titleView(g_engine),
+ _areYouReady(g_engine),
+ _mainMenu(g_engine) {
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
new file mode 100644
index 00000000000..c0e5d71a8ba
--- /dev/null
+++ b/engines/mm/mm1/views/dialogs.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_DIALOGS_H
+#define MM1_VIEWS_DIALOGS_H
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/views/title_view.h"
+#include "mm/mm1/views/are_you_ready.h"
+#include "mm/mm1/views/main_menu.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+struct Dialogs {
+private:
+ Views::TitleView _titleView;
+ Views::AreYouReady _areYouReady;
+ Views::MainMenu _mainMenu;
+public:
+ Dialogs();
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/main_menu.cpp b/engines/mm/mm1/views/main_menu.cpp
index c862fc5f151..faa24849760 100644
--- a/engines/mm/mm1/views/main_menu.cpp
+++ b/engines/mm/mm1/views/main_menu.cpp
@@ -20,15 +20,42 @@
*/
#include "mm/mm1/views/main_menu.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
namespace Views {
void MainMenu::draw() {
- // TODO
drawTextBorder();
- writeString(10, 10, "Main menu");
+ writeString(12, 4, STRING["dialogs.main_menu.title1"]);
+ writeString(6, 6, STRING["dialogs.main_menu.title2"]);
+ writeString(15, 9, STRING["dialogs.main_menu.title3"]);
+ writeString(15, 10, STRING["dialogs.main_menu.title4"]);
+
+ writeString(5, 12, STRING["dialogs.main_menu.option1"]);
+ writeString(5, 14, STRING["dialogs.main_menu.option2"]);
+ writeString(5, 16, STRING["dialogs.main_menu.option3"]);
+ writeString(4, 22, STRING["dialogs.main_menu.copyright1"]);
+ writeString(10, 24, STRING["dialogs.main_menu.copyright2"]);
+}
+
+bool MainMenu::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_c:
+ g_engine->replaceView("CreateCharacters");
+ return true;
+
+ case Common::KEYCODE_v:
+ g_engine->replaceView("ViewAllCharacters");
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/main_menu.h b/engines/mm/mm1/views/main_menu.h
index e435fa7c5eb..e8a008e32a1 100644
--- a/engines/mm/mm1/views/main_menu.h
+++ b/engines/mm/mm1/views/main_menu.h
@@ -37,6 +37,7 @@ public:
}
void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index d6b1852ac44..93daf3b6f6f 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS := \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
mm1/views/are_you_ready.o \
+ mm1/views/dialogs.o \
mm1/views/main_menu.o \
mm1/views/title_view.o \
mm1/views/text_view.o \
Commit: faf69883b9980683eb5212b433d359e7223b3450
https://github.com/scummvm/scummvm/commit/faf69883b9980683eb5212b433d359e7223b3450
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: Remove uiParent parameter in view constructors
Changed paths:
A engines/mm/mm1/views/title.cpp
A engines/mm/mm1/views/title.h
R engines/mm/mm1/views/title_view.cpp
R engines/mm/mm1/views/title_view.h
engines/mm/mm1/views/are_you_ready.h
engines/mm/mm1/views/dialogs.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/main_menu.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/are_you_ready.h b/engines/mm/mm1/views/are_you_ready.h
index bb57d4defc9..d3fca576a36 100644
--- a/engines/mm/mm1/views/are_you_ready.h
+++ b/engines/mm/mm1/views/are_you_ready.h
@@ -30,8 +30,7 @@ namespace Views {
class AreYouReady : public TextView {
public:
- AreYouReady(UIElement *uiParent = nullptr) :
- TextView("AreYouReady", uiParent) {}
+ AreYouReady() : TextView("AreYouReady") {}
virtual ~AreYouReady() {}
void draw() override;
diff --git a/engines/mm/mm1/views/dialogs.cpp b/engines/mm/mm1/views/dialogs.cpp
index b7bfec56e1d..a7e89d74b9a 100644
--- a/engines/mm/mm1/views/dialogs.cpp
+++ b/engines/mm/mm1/views/dialogs.cpp
@@ -26,12 +26,6 @@ namespace MM {
namespace MM1 {
namespace Views {
-Dialogs::Dialogs() :
- _titleView(g_engine),
- _areYouReady(g_engine),
- _mainMenu(g_engine) {
-}
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index c0e5d71a8ba..253d0578627 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -23,7 +23,7 @@
#define MM1_VIEWS_DIALOGS_H
#include "mm/mm1/events.h"
-#include "mm/mm1/views/title_view.h"
+#include "mm/mm1/views/title.h"
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/main_menu.h"
@@ -33,11 +33,11 @@ namespace Views {
struct Dialogs {
private:
- Views::TitleView _titleView;
+ Views::Title _title;
Views::AreYouReady _areYouReady;
Views::MainMenu _mainMenu;
public:
- Dialogs();
+ Dialogs() {}
};
} // namespace Views
diff --git a/engines/mm/mm1/views/main_menu.h b/engines/mm/mm1/views/main_menu.h
index e8a008e32a1..87bf4457856 100644
--- a/engines/mm/mm1/views/main_menu.h
+++ b/engines/mm/mm1/views/main_menu.h
@@ -30,9 +30,7 @@ namespace Views {
class MainMenu : public TextView {
public:
- MainMenu(UIElement *uiParent = nullptr) :
- TextView("MainMenu", uiParent) {
- }
+ MainMenu() : TextView("MainMenu") {}
virtual ~MainMenu() {
}
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 3b2fd856558..07b0e9ea322 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -22,11 +22,16 @@
#include "mm/mm1/globals.h"
#include "mm/mm1/gfx/gfx.h"
#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
namespace Views {
+TextView::TextView(const Common::String &name) :
+ UIElement(name, g_engine) {
+}
+
void TextView::writeChar(int x, int y, char c) {
g_globals->_font->drawChar(getScreen(), c,
x * FONT_SIZE, y * FONT_SIZE, 0xff);
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index d56605eef3f..86896f98e0b 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -45,8 +45,7 @@ protected:
*/
void writeString(int x, int y, const Common::String &str);
public:
- TextView(const Common::String &name, UIElement *uiParent = nullptr) :
- UIElement(name, uiParent) {}
+ TextView(const Common::String &name);
virtual ~TextView() {}
};
diff --git a/engines/mm/mm1/views/title_view.cpp b/engines/mm/mm1/views/title.cpp
similarity index 89%
rename from engines/mm/mm1/views/title_view.cpp
rename to engines/mm/mm1/views/title.cpp
index bfe70f46cd4..2383e08aa97 100644
--- a/engines/mm/mm1/views/title_view.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -19,14 +19,15 @@
*
*/
-#include "mm/mm1/views/title_view.h"
+#include "mm/mm1/views/title.h"
#include "mm/mm1/gfx/screen_decoder.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
namespace Views {
-TitleView::TitleView(UIElement *uiParent) : UIElement("Title", uiParent) {
+Title::Title() : UIElement("Title", g_engine) {
Gfx::ScreenDecoder decoder;
if (decoder.loadFile("screen0")) {
_surface.copyFrom(decoder.getSurface());
@@ -35,7 +36,7 @@ TitleView::TitleView(UIElement *uiParent) : UIElement("Title", uiParent) {
}
}
-void TitleView::draw() {
+void Title::draw() {
getScreen()->blitFrom(_surface);
}
diff --git a/engines/mm/mm1/views/title_view.h b/engines/mm/mm1/views/title.h
similarity index 86%
rename from engines/mm/mm1/views/title_view.h
rename to engines/mm/mm1/views/title.h
index 4b745022b10..f20d52b5702 100644
--- a/engines/mm/mm1/views/title_view.h
+++ b/engines/mm/mm1/views/title.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MM1_VIEWS_TITLE_VIEW_H
-#define MM1_VIEWS_TITLE_VIEW_H
+#ifndef MM1_VIEWS_TITLE_H
+#define MM1_VIEWS_TITLE_H
#include "mm/mm1/events.h"
@@ -28,12 +28,12 @@ namespace MM {
namespace MM1 {
namespace Views {
-class TitleView : public UIElement {
+class Title : public UIElement {
private:
Graphics::ManagedSurface _surface;
public:
- TitleView(UIElement *uiParent = nullptr);
- virtual ~TitleView() {}
+ Title();
+ virtual ~Title() {}
void draw() override;
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 93daf3b6f6f..55533047c32 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -10,9 +10,8 @@ MODULE_OBJS := \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
mm1/views/are_you_ready.o \
- mm1/views/dialogs.o \
mm1/views/main_menu.o \
- mm1/views/title_view.o \
+ mm1/views/title.o \
mm1/views/text_view.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
Commit: e5cc097f5d9287fa64036cce072066689a723214
https://github.com/scummvm/scummvm/commit/e5cc097f5d9287fa64036cce072066689a723214
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: Implementing view characters dialog
Changed paths:
A engines/mm/mm1/utils/roster.cpp
A engines/mm/mm1/utils/roster.h
A engines/mm/mm1/utils/strings.cpp
A engines/mm/mm1/utils/strings.h
A engines/mm/mm1/views/view_characters.cpp
A engines/mm/mm1/views/view_characters.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/globals.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 5f209223108..0e0cbf10c7e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -12,3 +12,29 @@ dialogs:
option3: "'#'.......GO TO TOWN"
copyright1: "COPR. 1986,1987-JON VAN CANEGHEM"
copyright2: "ALL RIGHTS RESERVED"
+ view_characters:
+ title: "VIEW ALL CHARACTERS"
+ legend1: "'A'-'%c' TO VIEW A CHARACTER"
+ legend2: "'ESC' TO GO BACK"
+classes:
+ 1: "1) KNIGHT "
+ 2: "2) PALADIN "
+ 3: "3) ARCHER "
+ 4: "4) CLERIC "
+ 5: "5) SORCERER"
+ 6: "6) ROBBER "
+ none: "NONE"
+races:
+ 1: "1) HUMAN "
+ 2: "2) ELF "
+ 3: "3) DWARF "
+ 4: "4) GNOME "
+ 5: "5) HALF-ORC "
+alignments:
+ 1: "1) GOOD "
+ 2: "2) NEUT "
+ 3: "3) EVIL "
+sex:
+ 1: "1) MALE "
+ 2: "2) FEMALE "
+ 3: "3) YES PLEASE"
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index ac9097854a3..52d3448cc0f 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -99,6 +99,14 @@ void Events::addView(const Common::String &name) {
addView(findView(name));
}
+void Events::popView() {
+ focusedView()->msgUnfocus(UnfocusMessage());
+ _views.pop();
+
+ if (!_views.empty())
+ focusedView()->msgFocus(FocusMessage());
+}
+
/*-------------------------------------------------------------------*/
UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
@@ -128,6 +136,11 @@ void UIElement::focus() {
g_engine->replaceView(this);
}
+void UIElement::close() {
+ assert(g_engine->focusedView() == this);
+ g_engine->popView();
+}
+
bool UIElement::tick() {
for (size_t i = 0; i < _children.size(); ++i) {
if (_children[i]->tick())
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 73e0aee2762..06168745fed 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -76,6 +76,12 @@ public:
*/
void focus();
+ /**
+ * Closes the current view. The view must have been added
+ * via addView, so there's a remaining view afterwards
+ */
+ void close();
+
/**
* Returns the game view
*/
@@ -120,13 +126,6 @@ class Events : public UIElement {
private:
Graphics::Screen *_screen = nullptr;
Common::Stack<UIElement *> _views;
-private:
- /**
- * Returns the currently focused view, if any
- */
- UIElement *focusedView() const {
- return _views.empty() ? nullptr : _views.top();
- }
protected:
/**
* Process an event
@@ -153,6 +152,18 @@ public:
void addView(UIElement *ui);
void addView(const Common::String &name);
+ /**
+ * Pops a view from the view stack
+ */
+ void popView();
+
+ /**
+ * Returns the currently focused view, if any
+ */
+ UIElement *focusedView() const {
+ return _views.empty() ? nullptr : _views.top();
+ }
+
Graphics::Screen *getScreen() const override {
return _screen;
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index cfc4b66dfbc..c04864743b9 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -24,6 +24,7 @@
#include "graphics/font.h"
#include "mm/utils/strings_data.h"
+#include "mm/mm1/utils/roster.h"
namespace MM {
namespace MM1 {
@@ -31,6 +32,7 @@ namespace MM1 {
class Globals {
public:
StringsData _strings;
+ Roster _roster;
const Graphics::Font *_font = nullptr;
public:
Globals();
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
new file mode 100644
index 00000000000..1aebb99edeb
--- /dev/null
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -0,0 +1,29 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/utils/roster.h"
+
+namespace MM {
+namespace MM1 {
+
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
new file mode 100644
index 00000000000..f60ebdd2987
--- /dev/null
+++ b/engines/mm/mm1/utils/roster.h
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_UTILS_ROSTER_H
+#define MM1_UTILS_ROSTER_H
+
+#include "common/serializer.h"
+
+namespace MM {
+namespace MM1 {
+
+#define CHARACTERS_COUNT 18
+
+enum CharacterClass {
+ KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
+ SORCERER = 5, ROBBER = 6, NONE = 0
+};
+
+enum Race {
+ HUMAN = 1, ELF = 2, DWARF = 3, GNOME = 4, HALF_ORC = 5
+};
+
+enum Alignment {
+ GOOD = 1, NEUTRAL = 2, EVIL = 3
+};
+
+enum Sex {
+ MALE = 1, FEMALE = 2, YES_PLEASE = 3
+};
+
+struct RosterEntry {
+ char _name[15] = { 0 };
+ uint8 _level = 0;
+ CharacterClass _class = NONE;
+};
+
+struct Roster {
+ RosterEntry _items[CHARACTERS_COUNT];
+ uint8 _nums[CHARACTERS_COUNT] = { 0 };
+
+ RosterEntry &operator[](uint idx) {
+ assert(idx < CHARACTERS_COUNT);
+ return _items[idx];
+ }
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/utils/strings.cpp b/engines/mm/mm1/utils/strings.cpp
new file mode 100644
index 00000000000..8feb11e6015
--- /dev/null
+++ b/engines/mm/mm1/utils/strings.cpp
@@ -0,0 +1,33 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/utils/strings.h"
+
+namespace MM {
+namespace MM1 {
+
+void pad_string(Common::String &str, size_t len, char c) {
+ while (str.size() < len)
+ str += c;
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/utils/strings.h b/engines/mm/mm1/utils/strings.h
new file mode 100644
index 00000000000..033b7c6bf5f
--- /dev/null
+++ b/engines/mm/mm1/utils/strings.h
@@ -0,0 +1,35 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_UTILS_STRINGS_H
+#define MM1_UTILS_STRINGS_H
+
+#include "common/str.h"
+
+namespace MM {
+namespace MM1 {
+
+extern void pad_string(Common::String &str, size_t len, char c = ' ');
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
new file mode 100644
index 00000000000..e58dcf8e39d
--- /dev/null
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/utils/strings.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void ViewCharacters::draw() {
+ Roster &roster = g_globals->_roster;
+ writeString(0, 11, STRING["dialogs.view_characters.title"]);
+ int lineNum = 0;
+ _charIndexes.clear();
+
+ // Loop to print characters
+ for (int charNum = 0; charNum < 18; ++charNum) {
+ if (roster._nums[charNum]) {
+ const RosterEntry &re = roster[charNum];
+ Common::String charName = re._name;
+ pad_string(charName, 16, '.');
+
+ Common::String level = Common::String::format("(%d)L%d",
+ roster._nums[charNum], re._level);
+ pad_string(level, 7);
+
+ Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
+ STRING[Common::String::format("classes.%d", (int)re._class)] :
+ STRING["classes.none"];
+
+ // Form line like: A) charName...(1)L1 Knight
+ Common::String line = Common::String::format("(%c) %s%s%s",
+ 'A' + lineNum, charName.c_str(), level.c_str(), className.c_str());
+ writeString(3, 3 + lineNum++, line);
+
+ _charIndexes.push_back(charNum);
+ }
+ }
+
+ // Print legend at the bottom
+ writeString(6, 22, Common::String::format(
+ STRING["dialogs.view_characters.legend1"].c_str(),
+ 'A' + (int)_charIndexes.size() - 1));
+ writeString(12, 24, STRING["dialogs.view_characters.legend2"]);
+}
+
+bool ViewCharacters::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ } else if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode <= (Common::KEYCODE_a + (int)_charIndexes.size() - 1)) {
+ // Character selected
+ warning("TODO: View character");
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/view_characters.h
new file mode 100644
index 00000000000..ddc4bc55715
--- /dev/null
+++ b/engines/mm/mm1/views/view_characters.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_VIEW_CHARACTERS_H
+#define MM1_VIEWS_VIEW_CHARACTERS_H
+
+#include "common/array.h"
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class ViewCharacters : public TextView {
+private:
+ Common::Array<uint> _charIndexes;
+public:
+ ViewCharacters() : TextView("ViewCharacters") {}
+ virtual ~ViewCharacters() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 55533047c32..c16ee68ce63 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -9,10 +9,13 @@ MODULE_OBJS := \
mm1/mm1.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
+ mm1/utils/roster.o \
+ mm1/utils/strings.o \
mm1/views/are_you_ready.o \
mm1/views/main_menu.o \
mm1/views/title.o \
mm1/views/text_view.o \
+ mm1/views/view_characters.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
xeen/worldofxeen/worldofxeen_cutscenes.o \
Commit: 7b3cb3f12aa87c2d1730561e6a8caa5315eccfad
https://github.com/scummvm/scummvm/commit/7b3cb3f12aa87c2d1730561e6a8caa5315eccfad
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: Adding display of character stats
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/gfx/gfx.h
engines/mm/mm1/globals.h
engines/mm/mm1/utils/roster.cpp
engines/mm/mm1/utils/roster.h
engines/mm/mm1/views/are_you_ready.cpp
engines/mm/mm1/views/main_menu.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/mm1/views/view_characters.cpp
engines/mm/mm1/views/view_characters.h
engines/mm/utils/engine_data.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 0e0cbf10c7e..dc4539ad57e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -16,25 +16,57 @@ dialogs:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
legend2: "'ESC' TO GO BACK"
-classes:
- 1: "1) KNIGHT "
- 2: "2) PALADIN "
- 3: "3) ARCHER "
- 4: "4) CLERIC "
- 5: "5) SORCERER"
- 6: "6) ROBBER "
+ view_character:
+ rename: "(CTRL)-'N' RE-NAME CHARACTER"
+ delete: "(CTRL)-'D' DELETE CHARACTER"
+stats:
none: "NONE"
-races:
- 1: "1) HUMAN "
- 2: "2) ELF "
- 3: "3) DWARF "
- 4: "4) GNOME "
- 5: "5) HALF-ORC "
-alignments:
- 1: "1) GOOD "
- 2: "2) NEUT "
- 3: "3) EVIL "
-sex:
- 1: "1) MALE "
- 2: "2) FEMALE "
- 3: "3) YES PLEASE"
+ classes:
+ 1: "1) KNIGHT "
+ 2: "2) PALADIN "
+ 3: "3) ARCHER "
+ 4: "4) CLERIC "
+ 5: "5) SORCERER"
+ 6: "6) ROBBER "
+ races:
+ 1: "1) HUMAN "
+ 2: "2) ELF "
+ 3: "3) DWARF "
+ 4: "4) GNOME "
+ 5: "5) HALF-ORC "
+ alignments:
+ 1: "1) GOOD "
+ 2: "2) NEUT "
+ 3: "3) EVIL "
+ sex:
+ 1: "1) MALE "
+ 2: "2) FEMALE "
+ 3: "3) YES PLEASE"
+ conditions:
+ cond: "COND="
+ good: "GOOD"
+ eradicated: "ERADICATED"
+ dead: "DEAD,"
+ stone: "STONE,"
+ unconscious: "UNCONSCIOUS,"
+ paralyzed: "PARALYZED,"
+ poisoned: "POISONED,"
+ diseased: "DISEASED,"
+ silenced: "SILENCED,"
+ blinded: "BLINDED,"
+ asleep: "ASLEEP,"
+ attributes:
+ int: "INT="
+ level: "LEVEL="
+ age: "AGE="
+ exp: "EXP="
+ mgt: "MGT="
+ per: "PER="
+ sp: "SP="
+ gems: "GEMS="
+ end: "END="
+ spd: "SPD="
+ hp: "HP="
+ gold: "GOLD="
+ acy: "ACY="
+ luc: "LUC="
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 52d3448cc0f..673121aa700 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -31,6 +31,16 @@ namespace MM1 {
#define FRAME_RATE 20
#define FRAME_DELAY (1000 / FRAME_RATE)
+Events *g_events;
+
+Events::Events() : UIElement("", nullptr) {
+ g_events = this;
+}
+
+Events::~Events() {
+ g_events = nullptr;
+}
+
void Events::runGame() {
Views::Dialogs dialogsContainer; // Load up all the dialogs
@@ -107,7 +117,7 @@ void Events::popView() {
focusedView()->msgFocus(FocusMessage());
}
-/*-------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
_name(name), _parent(uiParent) {
@@ -163,6 +173,21 @@ UIElement *UIElement::findView(const Common::String &name) {
return nullptr;
}
+void UIElement::replaceView(UIElement *ui) {
+ g_events->replaceView(ui);
+}
+
+void UIElement::replaceView(const Common::String &name) {
+ g_events->replaceView(name);
+}
+
+void UIElement::addView(UIElement *ui) {
+ g_events->addView(ui);
+}
+
+void UIElement::addView(const Common::String &name) {
+ g_events->addView(name);
+}
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 06168745fed..5fa1a2bff79 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -32,9 +32,7 @@ namespace MM1 {
class Events;
-struct Message {
-};
-
+struct Message {};
struct FocusMessage : public Message {};
struct UnfocusMessage : public Message {};
@@ -82,6 +80,18 @@ public:
*/
void close();
+ /**
+ * Sets the focus to a new view
+ */
+ void replaceView(UIElement *ui);
+ void replaceView(const Common::String &name);
+
+ /**
+ * Adds a focused view to the view stack without replacing current one
+ */
+ void addView(UIElement *ui);
+ void addView(const Common::String &name);
+
/**
* Returns the game view
*/
@@ -132,8 +142,8 @@ protected:
*/
void processEvent(Common::Event &ev);
public:
- Events() : UIElement("", nullptr) {}
- virtual ~Events() {}
+ Events();
+ virtual ~Events();
/**
* Main game loop
@@ -192,6 +202,8 @@ public:
#undef MESSAGE
};
+extern Events *g_events;
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/gfx/gfx.h b/engines/mm/mm1/gfx/gfx.h
index b3119d3ec1f..9a10b171810 100644
--- a/engines/mm/mm1/gfx/gfx.h
+++ b/engines/mm/mm1/gfx/gfx.h
@@ -28,9 +28,6 @@ namespace MM {
namespace MM1 {
namespace Gfx {
-#define FONT_SIZE 8
-#define TEXT_W 40
-#define TEXT_H 25
#define SCREEN_W 320
#define SCREEN_H 200
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index c04864743b9..a6754bdfc20 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -34,6 +34,7 @@ public:
StringsData _strings;
Roster _roster;
const Graphics::Font *_font = nullptr;
+ RosterEntry *_rosterEntry = nullptr;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
index 1aebb99edeb..2c4ad540a61 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -24,6 +24,20 @@
namespace MM {
namespace MM1 {
+void RosterEntry::synchronize(Common::Serializer &s) {
+ s.syncBytes((byte *)_name, 16);
+ s.skip(5);
+ s.syncAsByte(_class);
+
+}
+
+void Roster::synchronize(Common::Serializer &s) {
+ for (int i = 0; i < CHARACTERS_COUNT; ++i)
+ _items[i].synchronize(s);
+
+ for (int i = 0; i < CHARACTERS_COUNT; ++i)
+ s.syncAsByte(_nums[i]);
+}
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
index f60ebdd2987..b58fc978d0b 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/utils/roster.h
@@ -46,10 +46,34 @@ enum Sex {
MALE = 1, FEMALE = 2, YES_PLEASE = 3
};
+enum Condition {
+ FINE = 0, BAD_CONDITION = 0x80, ERADICATED = 0xff,
+ DEAD = 0x40, STONE = 0x20,
+ UNCONSCIOUS = 0x40, PARALYZED = 0x20, POISONED = 0x10,
+ DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
+};
+
struct RosterEntry {
- char _name[15] = { 0 };
- uint8 _level = 0;
+ char _name[16] = { 0 };
+ Sex _sex = MALE;
+ Alignment _alignment = GOOD;
+ Race _race = HUMAN;
CharacterClass _class = NONE;
+ uint8 _int = 0, _mgt = 0, _per = 0, _end = 0;
+ uint8 _spd = 0, _acy = 0, _luc = 0;
+ uint8 _level = 0;
+ uint8 _age = 0;
+ uint32 _exp = 0;
+ uint16 _sp = 0, _spMax = 0;
+ uint8 _sp1 = 0;
+ uint16 _gems = 0;
+ uint16 _hp = 0, _hpMax = 0;
+ uint16 _gold = 0;
+ byte _ac = 0;
+ uint8 _food = 0;
+ uint8 _condition = 0;
+
+ void synchronize(Common::Serializer &s);
};
struct Roster {
@@ -60,6 +84,8 @@ struct Roster {
assert(idx < CHARACTERS_COUNT);
return _items[idx];
}
+
+ void synchronize(Common::Serializer &s);
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/are_you_ready.cpp b/engines/mm/mm1/views/are_you_ready.cpp
index e41ad1c6164..83336505d8c 100644
--- a/engines/mm/mm1/views/are_you_ready.cpp
+++ b/engines/mm/mm1/views/are_you_ready.cpp
@@ -35,7 +35,7 @@ void AreYouReady::draw() {
bool AreYouReady::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_RETURN) {
- g_engine->replaceView("MainMenu");
+ replaceView("MainMenu");
return true;
}
diff --git a/engines/mm/mm1/views/main_menu.cpp b/engines/mm/mm1/views/main_menu.cpp
index faa24849760..da24d3f894d 100644
--- a/engines/mm/mm1/views/main_menu.cpp
+++ b/engines/mm/mm1/views/main_menu.cpp
@@ -44,11 +44,11 @@ void MainMenu::draw() {
bool MainMenu::msgKeypress(const KeypressMessage &msg) {
switch (msg.keycode) {
case Common::KEYCODE_c:
- g_engine->replaceView("CreateCharacters");
+ replaceView("CreateCharacters");
return true;
case Common::KEYCODE_v:
- g_engine->replaceView("ViewAllCharacters");
+ replaceView("ViewAllCharacters");
return true;
default:
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 07b0e9ea322..8b28403f402 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -32,14 +32,46 @@ TextView::TextView(const Common::String &name) :
UIElement(name, g_engine) {
}
-void TextView::writeChar(int x, int y, char c) {
+void TextView::writeChar(char c) {
g_globals->_font->drawChar(getScreen(), c,
- x * FONT_SIZE, y * FONT_SIZE, 0xff);
+ _textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
+
+ if (++_textPos.x == TEXT_W) {
+ _textPos.x = 0;
+ ++_textPos.y;
+ }
+}
+
+void TextView::writeChar(int x, int y, char c) {
+ _textPos.x = x;
+ _textPos.y = y;
+ writeChar(c);
+}
+
+void TextView::writeString(const Common::String &str) {
+ for (const char *s = str.c_str(); *s; ++s)
+ writeChar(*s);
}
void TextView::writeString(int x, int y, const Common::String &str) {
- for (const char *s = str.c_str(); *s; ++s, ++x)
- writeChar(x, y, *s);
+ _textPos.x = x;
+ _textPos.y = y;
+ writeString(str);
+}
+
+void TextView::writeNumber(int val) {
+ writeString(Common::String::format("%d", val));
+}
+
+void TextView::writeNumber(int x, int y, int val) {
+ _textPos.x = x;
+ _textPos.y = y;
+ writeNumber(val);
+}
+
+void TextView::newLine() {
+ _textPos.x = 0;
+ _textPos.y++;
}
void TextView::drawTextBorder() {
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 86896f98e0b..6baa21382e9 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -28,8 +28,14 @@ namespace MM {
namespace MM1 {
namespace Views {
+#define FONT_SIZE 8
+#define TEXT_W 40
+#define TEXT_H 25
+
class TextView : public UIElement {
protected:
+ Common::Point _textPos;
+
/**
* Draws a text border
*/
@@ -38,12 +44,25 @@ protected:
/**
* Write a character
*/
+ void writeChar(char c);
void writeChar(int x, int y, char c);
/**
* Write some text
*/
+ void writeString(const Common::String &str);
void writeString(int x, int y, const Common::String &str);
+
+ /**
+ * Write a number
+ */
+ void writeNumber(int val);
+ void writeNumber(int x, int y, int val);
+
+ /**
+ * Move the text position to the next line
+ */
+ void newLine();
public:
TextView(const Common::String &name);
virtual ~TextView() {}
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index e58dcf8e39d..7373a2370fe 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -46,7 +46,7 @@ void ViewCharacters::draw() {
Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
STRING[Common::String::format("classes.%d", (int)re._class)] :
- STRING["classes.none"];
+ STRING["stats.none"];
// Form line like: A) charName...(1)L1 Knight
Common::String line = Common::String::format("(%c) %s%s%s",
@@ -70,12 +70,164 @@ bool ViewCharacters::msgKeypress(const KeypressMessage &msg) {
} else if (msg.keycode >= Common::KEYCODE_a &&
msg.keycode <= (Common::KEYCODE_a + (int)_charIndexes.size() - 1)) {
// Character selected
- warning("TODO: View character");
+ g_globals->_rosterEntry = &g_globals->_roster[
+ msg.keycode - Common::KEYCODE_a];
+ addView("ViewCharacter");
}
return false;
}
+/*------------------------------------------------------------------------*/
+
+void CharacterStats::printStats() {
+ RosterEntry &re = *g_globals->_rosterEntry;
+ printSummary();
+
+ newLine();
+ writeString(STRING["stats.conditions.int"]);
+ writeNumber(re._int);
+ _textPos.x = 8;
+ writeString(STRING["stats.conditions.level"]);
+ writeNumber(re._level);
+ _textPos.x = 18;
+ writeString(STRING["stats.conditions.age"]);
+ writeNumber(re._level);
+ _textPos.x = 27;
+ writeString(STRING["stats.conditions.age"]);
+ writeNumber(re._exp);
+
+ newLine();
+ writeString(STRING["stats.conditions.mgt"]);
+ writeNumber(re._mgt);
+
+ newLine();
+ writeString(STRING["stats.conditions.per"]);
+ writeNumber(re._per);
+ _textPos.x = 8;
+ writeString(STRING["stats.conditions.sp"]);
+ writeNumber(re._sp);
+ _textPos.x = 16;
+ writeChar('/');
+ writeNumber(re._spMax);
+ _textPos.x = 22;
+ writeChar('(');
+ writeNumber(re._sp1);
+ writeChar(')');
+ _textPos.x = 26;
+ writeString(STRING["stats.conditions.gems"]);
+ writeNumber(re._gems);
+
+ newLine();
+ writeString(STRING["stats.conditions.end"]);
+ writeNumber(re._end);
+
+ newLine();
+ writeString(STRING["stats.conditions.spd"]);
+ writeNumber(re._spd);
+ _textPos.x = 8;
+ writeString(STRING["stats.conditions.hp"]);
+ writeNumber(re._hp);
+ _textPos.x = 16;
+ writeChar('/');
+ writeNumber(re._hpMax);
+ _textPos.x = 26;
+ writeString(STRING["stats.conditions.gold"]);
+ writeNumber(re._gold);
+
+ newLine();
+ writeString(STRING["stats.conditions.acy"]);
+ writeNumber(re._acy);
+
+ newLine();
+ writeString(STRING["stats.conditions.luc"]);
+ writeNumber(re._luc);
+ _textPos.x = 8;
+ writeString(STRING["stats.conditions.ac"]);
+ writeNumber(re._ac);
+ _textPos.x = 26;
+ writeString(STRING["stats.conditions.food"]);
+ writeNumber(re._food);
+
+ newLine();
+ newLine();
+ printCondition();
+}
+
+void CharacterStats::printSummary() {
+ RosterEntry &re = *g_globals->_rosterEntry;
+ writeString(1, 0, re._name);
+ writeString(17, 0, Common::String::format(": %c %s",
+ (re._sex == MALE) ? 'M' : (re._sex == FEMALE ? 'F' : 'O'),
+ (re._alignment >= GOOD && re._alignment <= EVIL) ?
+ STRING[Common::String::format("alignments.%d", re._alignment)].c_str() + 3 :
+ STRING["stats.none"].c_str()
+ ));
+
+ if (re._race >= HUMAN && re._race <= HALF_ORC)
+ writeString(26, 0, STRING[Common::String::format("races.%d", re._race)].c_str() + 3);
+ else
+ writeString(26, 0, STRING["stats.none"]);
+
+ if (re._class >= KNIGHT && re._class <= ROBBER)
+ writeString(32, 0, STRING[Common::String::format("classes.%d", re._class)].c_str() + 3);
+ else
+ writeString(32, 0, STRING["stats.none"]);
+}
+
+void CharacterStats::printCondition() {
+ RosterEntry &re = *g_globals->_rosterEntry;
+ writeString(STRING["stats.conditions.cond"]);
+ int cond = re._condition;
+
+ if (cond == 0) {
+ writeString(STRING["stats.conditions.good"]);
+ } else if (cond == ERADICATED) {
+ writeString(STRING["stats.conditions.eradicated"]);
+ } else {
+ if (cond & BAD_CONDITION) {
+ // Fatal conditions
+ if (cond & DEAD)
+ writeString(STRING["stats.conditions.dead"]);
+ if (cond & STONE)
+ writeString(STRING["stats.conditions.stone"]);
+ } else {
+ if (cond & UNCONSCIOUS)
+ writeString(STRING["stats.conditions.unconscious"]);
+ if (cond & PARALYZED)
+ writeString(STRING["stats.conditions.paralyzed"]);
+ if (cond & POISONED)
+ writeString(STRING["stats.conditions.poisoned"]);
+ if (cond & DISEASED)
+ writeString(STRING["stats.conditions.diseased"]);
+ if (cond & SILENCED)
+ writeString(STRING["stats.conditions.silenced"]);
+ if (cond & BLINDED)
+ writeString(STRING["stats.conditions.blinded"]);
+ if (cond & ASLEEP)
+ writeString(STRING["stats.conditions.asleep"]);
+ }
+
+ --_textPos.x;
+ writeChar(' ');
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+void ViewCharacter::draw() {
+ assert(g_globals->_rosterEntry);
+// RosterEntry &re = *g_globals->_rosterEntry;
+
+ Graphics::ManagedSurface *scr = getScreen();
+ scr->clear();
+
+}
+
+bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
+ return false;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/view_characters.h
index ddc4bc55715..2c0b79e5d68 100644
--- a/engines/mm/mm1/views/view_characters.h
+++ b/engines/mm/mm1/views/view_characters.h
@@ -40,6 +40,27 @@ public:
bool msgKeypress(const KeypressMessage &msg) override;
};
+class CharacterStats : public TextView {
+protected:
+ void printStats();
+ void printSummary();
+ void printCondition();
+ void printInventory();
+public:
+ CharacterStats(const Common::String &name) : TextView(name) {}
+ ~CharacterStats() {}
+};
+
+class ViewCharacter : public CharacterStats {
+public:
+ ViewCharacter() : CharacterStats("ViewCharacter") {}
+ virtual ~ViewCharacter() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/utils/engine_data.cpp b/engines/mm/utils/engine_data.cpp
index 8626d997388..5c9bdc6ea3c 100644
--- a/engines/mm/utils/engine_data.cpp
+++ b/engines/mm/utils/engine_data.cpp
@@ -210,7 +210,7 @@ Common::SeekableReadStream *DataArchive::createReadStreamForMember(const Common:
return nullptr;
}
-/*-------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
#ifndef RELEASE_BUILD
@@ -251,7 +251,7 @@ Common::FSNode DataArchiveProxy::getNode(const Common::String &name) const {
#endif
-/*-------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
bool load_engine_data(const Common::String &subfolder, int reqMajorVersion,
int reqMinorVersion, Common::U32String &errorMsg, bool useDataPrefix) {
Commit: 15cf35f9d6ae3481e6f70a92d4431a5270d874d7
https://github.com/scummvm/scummvm/commit/15cf35f9d6ae3481e6f70a92d4431a5270d874d7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:42+01:00
Commit Message:
MM: MM1: Load roster, fixes to the view character dialog
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/utils/roster.cpp
engines/mm/mm1/utils/roster.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/main_menu.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/mm1/views/view_characters.cpp
engines/mm/mm1/views/view_characters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index dc4539ad57e..719a8730ca0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -19,6 +19,8 @@ dialogs:
view_character:
rename: "(CTRL)-'N' RE-NAME CHARACTER"
delete: "(CTRL)-'D' DELETE CHARACTER"
+ misc:
+ go_back: "'ESC' TO GO BACK"
stats:
none: "NONE"
classes:
@@ -43,7 +45,6 @@ stats:
2: "2) FEMALE "
3: "3) YES PLEASE"
conditions:
- cond: "COND="
good: "GOOD"
eradicated: "ERADICATED"
dead: "DEAD,"
@@ -70,3 +71,6 @@ stats:
gold: "GOLD="
acy: "ACY="
luc: "LUC="
+ ac: "AC="
+ food: "FOOD="
+ cond: "COND="
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 673121aa700..36e4291dd50 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -89,6 +89,7 @@ void Events::replaceView(UIElement *ui) {
}
_views.push(ui);
+ ui->redraw();
ui->msgFocus(FocusMessage());
}
@@ -102,6 +103,7 @@ void Events::addView(UIElement *ui) {
focusedView()->msgUnfocus(UnfocusMessage());
_views.push(ui);
+ ui->redraw();
ui->msgFocus(FocusMessage());
}
@@ -113,8 +115,10 @@ void Events::popView() {
focusedView()->msgUnfocus(UnfocusMessage());
_views.pop();
- if (!_views.empty())
+ if (!_views.empty()) {
+ focusedView()->redraw();
focusedView()->msgFocus(FocusMessage());
+ }
}
/*------------------------------------------------------------------------*/
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index a238d2ab1a3..0a0c1a280da 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -49,6 +49,9 @@ bool Globals::load() {
if (!_strings.load("strings_en.yml"))
return false;
+ // Load default roster
+ _roster.loadDefaults();
+
// Load the font
_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index a6754bdfc20..0fc7baab70c 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -43,11 +43,19 @@ public:
* Loads data for the globals
*/
bool load();
+
+ /**
+ * Returns a string
+ */
+ const Common::String &operator[](const Common::String &name) {
+ assert(_strings.contains(name));
+ return _strings[name];
+ }
};
extern Globals *g_globals;
-#define STRING (g_globals->_strings)
+#define STRING (*g_globals)
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
index 2c4ad540a61..91f302aaf9b 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/file.h"
#include "mm/mm1/utils/roster.h"
namespace MM {
@@ -26,9 +27,47 @@ namespace MM1 {
void RosterEntry::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
- s.skip(5);
+ s.syncAsByte(_sex);
+ s.skip(1);
+ s.syncAsByte(_alignment);
+ s.syncAsByte(_race);
s.syncAsByte(_class);
+ s.skip(1);
+ s.syncAsByte(_int);
+ s.skip(1);
+ s.syncAsByte(_mgt);
+ s.skip(1);
+ s.syncAsByte(_per);
+ s.skip(1);
+ s.syncAsByte(_end);
+ s.skip(1);
+ s.syncAsByte(_spd);
+ s.skip(1);
+ s.syncAsByte(_acy);
+ s.skip(1);
+ s.syncAsByte(_luc);
+ s.skip(1);
+ s.syncAsByte(_level);
+ s.syncAsByte(_age);
+ s.skip(1);
+ s.syncAsUint32LE(_exp);
+ s.syncAsUint16LE(_sp);
+ s.syncAsUint16LE(_spMax);
+ s.skip(1);
+ s.syncAsByte(_sp1);
+ s.syncAsUint16LE(_gems);
+ s.syncAsUint16LE(_hp);
+ s.skip(2);
+ s.syncAsUint16LE(_hpMax);
+ s.syncAsUint16LE(_gold);
+ s.skip(2);
+ s.syncAsByte(_ac);
+ s.syncAsByte(_food);
+ s.syncAsByte(_condition);
+
+ // TODO: Inventory
+ s.skip(0x3f);
}
void Roster::synchronize(Common::Serializer &s) {
@@ -39,5 +78,14 @@ void Roster::synchronize(Common::Serializer &s) {
s.syncAsByte(_nums[i]);
}
+void Roster::loadDefaults() {
+ Common::File f;
+ if (!f.open("roster.dta"))
+ error("Could not open roster.dta");
+
+ Common::Serializer s(&f, nullptr);
+ synchronize(s);
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
index b58fc978d0b..fd4db9c1de6 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/utils/roster.h
@@ -86,6 +86,7 @@ struct Roster {
}
void synchronize(Common::Serializer &s);
+ void loadDefaults();
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 253d0578627..4e0bc7e016b 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -26,6 +26,7 @@
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/main_menu.h"
+#include "mm/mm1/views/view_characters.h"
namespace MM {
namespace MM1 {
@@ -33,9 +34,11 @@ namespace Views {
struct Dialogs {
private:
- Views::Title _title;
Views::AreYouReady _areYouReady;
Views::MainMenu _mainMenu;
+ Views::Title _title;
+ Views::ViewCharacters _characters;
+ Views::ViewCharacter _character;
public:
Dialogs() {}
};
diff --git a/engines/mm/mm1/views/main_menu.cpp b/engines/mm/mm1/views/main_menu.cpp
index da24d3f894d..bec1e298dee 100644
--- a/engines/mm/mm1/views/main_menu.cpp
+++ b/engines/mm/mm1/views/main_menu.cpp
@@ -44,11 +44,11 @@ void MainMenu::draw() {
bool MainMenu::msgKeypress(const KeypressMessage &msg) {
switch (msg.keycode) {
case Common::KEYCODE_c:
- replaceView("CreateCharacters");
+ addView("CreateCharacters");
return true;
case Common::KEYCODE_v:
- replaceView("ViewAllCharacters");
+ addView("ViewCharacters");
return true;
default:
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 8b28403f402..d30a36e0b93 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -98,6 +98,10 @@ void TextView::drawTextBorder() {
}
}
+void TextView::escToGoBack() {
+ writeString(12, 24, STRING["dialogs.misc.go_back"]);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 6baa21382e9..c14359d3e95 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -36,11 +36,6 @@ class TextView : public UIElement {
protected:
Common::Point _textPos;
- /**
- * Draws a text border
- */
- void drawTextBorder();
-
/**
* Write a character
*/
@@ -63,6 +58,16 @@ protected:
* Move the text position to the next line
*/
void newLine();
+
+ /**
+ * Draws a text border
+ */
+ void drawTextBorder();
+
+ /**
+ * Prints a message 'ESC' to go back
+ */
+ void escToGoBack();
public:
TextView(const Common::String &name);
virtual ~TextView() {}
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index 7373a2370fe..608118fda9d 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -28,8 +28,10 @@ namespace MM1 {
namespace Views {
void ViewCharacters::draw() {
+ drawTextBorder();
+
Roster &roster = g_globals->_roster;
- writeString(0, 11, STRING["dialogs.view_characters.title"]);
+ writeString(11, 0, STRING["dialogs.view_characters.title"]);
int lineNum = 0;
_charIndexes.clear();
@@ -45,7 +47,7 @@ void ViewCharacters::draw() {
pad_string(level, 7);
Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
- STRING[Common::String::format("classes.%d", (int)re._class)] :
+ STRING[Common::String::format("stats.classes.%d", (int)re._class)].c_str() + 3 :
STRING["stats.none"];
// Form line like: A) charName...(1)L1 Knight
@@ -85,27 +87,27 @@ void CharacterStats::printStats() {
printSummary();
newLine();
- writeString(STRING["stats.conditions.int"]);
+ writeString(STRING["stats.attributes.int"]);
writeNumber(re._int);
_textPos.x = 8;
- writeString(STRING["stats.conditions.level"]);
+ writeString(STRING["stats.attributes.level"]);
writeNumber(re._level);
_textPos.x = 18;
- writeString(STRING["stats.conditions.age"]);
+ writeString(STRING["stats.attributes.age"]);
writeNumber(re._level);
_textPos.x = 27;
- writeString(STRING["stats.conditions.age"]);
+ writeString(STRING["stats.attributes.exp"]);
writeNumber(re._exp);
newLine();
- writeString(STRING["stats.conditions.mgt"]);
+ writeString(STRING["stats.attributes.mgt"]);
writeNumber(re._mgt);
newLine();
- writeString(STRING["stats.conditions.per"]);
+ writeString(STRING["stats.attributes.per"]);
writeNumber(re._per);
_textPos.x = 8;
- writeString(STRING["stats.conditions.sp"]);
+ writeString(STRING["stats.attributes.sp"]);
writeNumber(re._sp);
_textPos.x = 16;
writeChar('/');
@@ -115,38 +117,38 @@ void CharacterStats::printStats() {
writeNumber(re._sp1);
writeChar(')');
_textPos.x = 26;
- writeString(STRING["stats.conditions.gems"]);
+ writeString(STRING["stats.attributes.gems"]);
writeNumber(re._gems);
newLine();
- writeString(STRING["stats.conditions.end"]);
+ writeString(STRING["stats.attributes.end"]);
writeNumber(re._end);
newLine();
- writeString(STRING["stats.conditions.spd"]);
+ writeString(STRING["stats.attributes.spd"]);
writeNumber(re._spd);
_textPos.x = 8;
- writeString(STRING["stats.conditions.hp"]);
+ writeString(STRING["stats.attributes.hp"]);
writeNumber(re._hp);
_textPos.x = 16;
writeChar('/');
writeNumber(re._hpMax);
_textPos.x = 26;
- writeString(STRING["stats.conditions.gold"]);
+ writeString(STRING["stats.attributes.gold"]);
writeNumber(re._gold);
newLine();
- writeString(STRING["stats.conditions.acy"]);
+ writeString(STRING["stats.attributes.acy"]);
writeNumber(re._acy);
newLine();
- writeString(STRING["stats.conditions.luc"]);
+ writeString(STRING["stats.attributes.luc"]);
writeNumber(re._luc);
_textPos.x = 8;
- writeString(STRING["stats.conditions.ac"]);
+ writeString(STRING["stats.attributes.ac"]);
writeNumber(re._ac);
_textPos.x = 26;
- writeString(STRING["stats.conditions.food"]);
+ writeString(STRING["stats.attributes.food"]);
writeNumber(re._food);
newLine();
@@ -157,27 +159,33 @@ void CharacterStats::printStats() {
void CharacterStats::printSummary() {
RosterEntry &re = *g_globals->_rosterEntry;
writeString(1, 0, re._name);
- writeString(17, 0, Common::String::format(": %c %s",
- (re._sex == MALE) ? 'M' : (re._sex == FEMALE ? 'F' : 'O'),
- (re._alignment >= GOOD && re._alignment <= EVIL) ?
- STRING[Common::String::format("alignments.%d", re._alignment)].c_str() + 3 :
- STRING["stats.none"].c_str()
- ));
+
+ _textPos.x = 17;
+ writeString(": ");
+
+ writeChar((re._sex == MALE) ? 'M' : (re._sex == FEMALE ? 'F' : 'O'));
+
+ _textPos.x++;
+ writeString((re._alignment >= GOOD && re._alignment <= EVIL) ?
+ STRING[Common::String::format("stats.alignments.%d", re._alignment)].c_str() + 3 :
+ STRING["stats.none"]
+ );
if (re._race >= HUMAN && re._race <= HALF_ORC)
- writeString(26, 0, STRING[Common::String::format("races.%d", re._race)].c_str() + 3);
+ writeString(26, 0, STRING[Common::String::format("stats.races.%d", re._race)].c_str() + 3);
else
writeString(26, 0, STRING["stats.none"]);
if (re._class >= KNIGHT && re._class <= ROBBER)
- writeString(32, 0, STRING[Common::String::format("classes.%d", re._class)].c_str() + 3);
+ writeString(32, 0, STRING[Common::String::format("stats.classes.%d", re._class)].c_str() + 3);
else
writeString(32, 0, STRING["stats.none"]);
}
void CharacterStats::printCondition() {
RosterEntry &re = *g_globals->_rosterEntry;
- writeString(STRING["stats.conditions.cond"]);
+ writeString(STRING["stats.attributes.cond"]);
+ _textPos.x++;
int cond = re._condition;
if (cond == 0) {
@@ -221,10 +229,18 @@ void ViewCharacter::draw() {
Graphics::ManagedSurface *scr = getScreen();
scr->clear();
+ printStats();
+ writeString(6, 21, STRING["dialogs.view_character.rename"]);
+ writeString(6, 22, STRING["dialogs.view_character.delete"]);
+ escToGoBack();
}
bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ }
+
return false;
}
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/view_characters.h
index 2c0b79e5d68..64ee40365c4 100644
--- a/engines/mm/mm1/views/view_characters.h
+++ b/engines/mm/mm1/views/view_characters.h
@@ -45,7 +45,6 @@ protected:
void printStats();
void printSummary();
void printCondition();
- void printInventory();
public:
CharacterStats(const Common::String &name) : TextView(name) {}
~CharacterStats() {}
Commit: bfb4b602a9d706683c115221b83676d80bed7704
https://github.com/scummvm/scummvm/commit/bfb4b602a9d706683c115221b83676d80bed7704
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Add loading roster inventories, display in character view
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/utils/roster.cpp
engines/mm/mm1/utils/roster.h
engines/mm/mm1/views/view_characters.cpp
engines/mm/mm1/views/view_characters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 719a8730ca0..316bd3cb868 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -23,6 +23,7 @@ dialogs:
go_back: "'ESC' TO GO BACK"
stats:
none: "NONE"
+ inventory: "-----<EQUIPPED>----------<BACKPACK>----".
classes:
1: "1) KNIGHT "
2: "2) PALADIN "
@@ -74,3 +75,259 @@ stats:
ac: "AC="
food: "FOOD="
cond: "COND="
+ items:
+ 1: "CLUB"
+ 2: "DAGGER"
+ 3: "HAND AXE"
+ 4: "SPEAR"
+ 5: "SHORT SWORD"
+ 6: "MACE"
+ 7: "FLAIL"
+ 8: "SCIMITAR"
+ 9: "BROAD SWORD"
+ 10: "BATTLE AXE"
+ 11: "LONG SWORD"
+ 12: "CLUB +1"
+ 13: "CLUB +2"
+ 14: "DAGGER +1"
+ 15: "HAND AXE +1"
+ 16: "SPEAR +1"
+ 17: "SHORT SWORD +1"
+ 18: "MACE +1"
+ 19: "FLAIL +1"
+ 20: "SCIMITAR +1"
+ 21: "BROAD SWORD +1"
+ 22: "BATTLE AXE +1"
+ 23: "LONG SWORD +1"
+ 24: "FLAMING CLUB"
+ 25: "CLUB OF NOISE"
+ 26: "DAGGER +2"
+ 27: "HAND AXE +2"
+ 28: "SPEAR +2"
+ 29: "SHORT SWORD +2"
+ 30: "MACE +2"
+ 31: "FLAIL +2"
+ 32: "SCIMITAR +2"
+ 33: "BROAD SWORD +2"
+ 34: "BATTLE AXE +2"
+ 35: "LONG SWORD +2"
+ 36: "ROYAL DAGGER"
+ 37: "DAGGER OF MIND"
+ 38: "DIAMOND DAGGER"
+ 39: "ELECTRIC SPEAR"
+ 40: "HOLY MACE"
+ 41: "UN-HOLY MACE"
+ 42: "DARK FLAIL"
+ 43: "FLAIL OF FEAR"
+ 44: "LUCKY SCIMITAR"
+ 45: "MACE OF UNDEAD"
+ 46: "COLD AXE"
+ 47: "ELECTRIC SWORD"
+ 48: "FLAMING SWORD"
+ 49: "SWORD OF MIGHT"
+ 50: "SWORD OF SPEED"
+ 51: "SHARP SWORD"
+ 52: "ACCURATE SWORD"
+ 53: "SWORD OF MAGIC"
+ 54: "IMMORTAL SWORD"
+ 55: "AXE PROTECTOR"
+ 56: "AXE DESTROYER"
+ 57: "X!XX!X'S SWORD"
+ 58: "ADAMTINE AXE"
+ 59: "ULTIMATE SWORD"
+ 60: "ELEMENT SWORD"
+ 61: "SLING"
+ 62: "CROSSBOW"
+ 63: "SHORT BOW"
+ 64: "LONG BOW"
+ 65: "GREAT BOW"
+ 66: "SLING +1"
+ 67: "CROSSBOW +1"
+ 68: "SHORT BOW +1"
+ 69: "LONG BOW +1"
+ 70: "GREAT BOW +1"
+ 71: "MAGIC SLING"
+ 72: "CROSSBOW +2"
+ 73: "SHORT BOW +2"
+ 74: "LONG BOW +2"
+ 75: "GREAT BOW +2"
+ 76: "CROSSBOW LUCK"
+ 77: "CROSSBOW SPEED"
+ 78: "LIGHTNING BOW"
+ 79: "FLAMING BOW"
+ 80: "GIANT'S BOW"
+ 81: "THE MAGIC BOW"
+ 82: "BOW OF POWER"
+ 83: "ROBBER'S X-BOW"
+ 84: "ARCHER'S BOW"
+ 85: "OBSIDIAN BOW"
+ 86: "STAFF"
+ 87: "GLAIVE"
+ 88: "BARDICHE"
+ 89: "HALBERD"
+ 90: "GREAT HAMMER"
+ 91: "GREAT AXE"
+ 92: "FLAMBERGE"
+ 93: "STAFF +1"
+ 94: "GLAIVE +1"
+ 95: "BARDICHE +1"
+ 96: "HALBERD +1"
+ 97: "GREAT HAMMER+1"
+ 98: "GREAT AXE +1"
+ 99: "FLAMBERGE +1"
+ 100: "STAFF +2"
+ 101: "GLAIVE +2"
+ 102: "BARDICHE +2"
+ 103: "HALBERD +2"
+ 104: "GREAT HAMMER+2"
+ 105: "GREAT AXE +2"
+ 106: "FLAMBERGE +2"
+ 107: "STAFF OF LIGHT"
+ 108: "COLD GLAIVE"
+ 109: "CURING STAFF"
+ 110: "MINOTAUR'S AXE"
+ 111: "THUNDER HAMMER"
+ 112: "GREAT AXE +3"
+ 113: "FLAMBERGE +3"
+ 114: "SORCERER STAFF"
+ 115: "STAFF OF MAGIC"
+ 116: "DEMON'S GLAIVE"
+ 117: "DEVIL'S GLAIVE"
+ 118: "THE FLAMBERGE"
+ 119: "HOLY FLAMBERGE"
+ 120: "EVIL FLAMBERGE"
+ 121: "PADDED ARMOR"
+ 122: "LEATHER ARMOR"
+ 123: "SCALE ARMOR"
+ 124: "RING MAIL"
+ 125: "CHAIN MAIL"
+ 126: "SPLINT MAIL"
+ 127: "PLATE MAIL"
+ 128: "PADDED +1"
+ 129: "LEATHER +1"
+ 130: "SCALE +1"
+ 131: "RING MAIL +1"
+ 132: "CHAIN MAIL +1"
+ 133: "SPLINT MAIL +1"
+ 134: "PLATE MAIL +1"
+ 135: "LEATHER +2"
+ 136: "SCALE +2"
+ 137: "RING MAIL +2"
+ 138: "CHAIN MAIL +2"
+ 139: "SPLINT MAIL +2"
+ 140: "PLATE MAIL +2"
+ 141: "BRACERS AC 4"
+ 142: "RING MAIL +3"
+ 143: "CHAIN MAIL +3"
+ 144: "SPLINT MAIL +3"
+ 145: "PLATE MAIL +3"
+ 146: "BRACERS AC 6"
+ 147: "CHAIN MAIL +3"
+ 148: "BRACERS AC 8"
+ 149: "BLUE RING MAIL"
+ 150: "RED CHAIN MAIL"
+ 151: "X!XX!X'S PLATE"
+ 152: "HOLY PLATE"
+ 153: "UN-HOLY PLATE"
+ 154: "ULTIMATE PLATE"
+ 155: "BRACERS AC 8"
+ 156: "SMALL SHIELD"
+ 157: "LARGE SHIELD"
+ 158: "SILVER SHIELD"
+ 159: "SMALL SHIELD+1"
+ 160: "LARGE SHIELD+1"
+ 161: "LARGE SHIELD+1"
+ 162: "SMALL SHIELD+2"
+ 163: "LARGE SHIELD+2"
+ 164: "LARGE SHIELD+2"
+ 165: "FIRE SHIELD"
+ 166: "COLD SHIELD"
+ 167: "ELEC SHIELD"
+ 168: "ACID SHIELD"
+ 169: "MAGIC SHIELD"
+ 170: "DRAGON SHIELD"
+ 171: "ROPE & HOOKS"
+ 172: "TORCH"
+ 173: "LANTERN"
+ 174: "10 FOOT POLE"
+ 175: "GARLIC"
+ 176: "WOLFSBANE"
+ 177: "BELLADONNA"
+ 178: "MAGIC HERBS"
+ 179: "DRIED BEEF"
+ 180: "ROBBER'S TOOLS"
+ 181: "BAG OF SILVER"
+ 182: "AMBER GEM"
+ 183: "SMELLING SALT"
+ 184: "BAG OF SAND"
+ 185: "MIGHT POTION"
+ 186: "SPEED POTION"
+ 187: "SUNDIAL"
+ 188: "CURING POTION"
+ 189: "MAGIC POTION"
+ 190: "DEFENSE RING"
+ 191: "BAG OF GARBAGE"
+ 192: "SCROLL OF FIRE"
+ 193: "FLYING CARPET"
+ 194: "JADE AMULET"
+ 195: "ANTIDOTE BREW"
+ 196: "SKILL POTION"
+ 197: "BOOTS OF SPEED"
+ 198: "LUCKY CHARM"
+ 199: "WAND OF FIRE"
+ 200: "UNDEAD AMULET"
+ 201: "SILENT CHIME"
+ 202: "BELT OF POWER"
+ 203: "MODEL BOAT"
+ 204: "DEFENSE CLOAK"
+ 205: "KNOWLEDGE BOOK"
+ 206: "RUBY IDOL"
+ 207: "SORCERER ROBE"
+ 208: "POWER GAUNTLET"
+ 209: "CLERIC'S BEADS"
+ 210: "HORN OF DEATH"
+ 211: "POTION OF LIFE"
+ 212: "SHINY PENDANT"
+ 213: "LIGHTNING WAND"
+ 214: "PRECISION RING"
+ 215: "RETURN SCROLL"
+ 216: "TELEPORT HELM"
+ 217: "YOUTH POTION"
+ 218: "BELLS OF TIME"
+ 219: "MAGIC OIL"
+ 220: "MAGIC VEST"
+ 221: "DESTROYER WAND"
+ 222: "ELEMENT SCARAB"
+ 223: "SUN SCROLL"
+ 224: "STAR RUBY"
+ 225: "STAR SAPPHIRE"
+ 226: "WEALTH CHEST"
+ 227: "GEM SACK"
+ 228: "DIAMOND COLLAR"
+ 229: "FIRE OPAL"
+ 230: "UNOBTAINIUM"
+ 231: "VELLUM SCROLL"
+ 232: "RUBY WHISTLE"
+ 233: "KINGS PASS"
+ 234: "MERCHANTS PASS"
+ 235: "CRYSTAL KEY"
+ 236: "CORAL KEY"
+ 237: "BRONZE KEY"
+ 238: "SILVER KEY"
+ 239: "GOLD KEY"
+ 240: "DIAMOND KEY"
+ 241: "CACTUS NECTAR"
+ 242: "MAP OF DESERT"
+ 243: "LASER BLASTER"
+ 244: "DRAGONS TOOTH"
+ 245: "WYVERN EYE"
+ 246: "MEDUSA HEAD"
+ 247: "RING OF OKRIM"
+ 248: "B QUEEN IDOL"
+ 249: "W QUEEN IDOL"
+ 250: "PIRATES MAP A"
+ 251: "PIRATES MAP B"
+ 252: "THUNDRANIUM"
+ 253: "KEY CARD"
+ 254: "EYE OF GORDOS"
+ 255: "(USELESS ITEM)"
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
index 91f302aaf9b..73c9d56939f 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -66,8 +66,10 @@ void RosterEntry::synchronize(Common::Serializer &s) {
s.syncAsByte(_food);
s.syncAsByte(_condition);
- // TODO: Inventory
- s.skip(0x3f);
+ s.syncBytes(_equipped, INVENTORY_COUNT);
+ s.syncBytes(_backpack, INVENTORY_COUNT);
+
+ s.skip(51);
}
void Roster::synchronize(Common::Serializer &s) {
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
index fd4db9c1de6..d5a83f985d5 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/utils/roster.h
@@ -28,6 +28,7 @@ namespace MM {
namespace MM1 {
#define CHARACTERS_COUNT 18
+#define INVENTORY_COUNT 6
enum CharacterClass {
KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
@@ -72,6 +73,8 @@ struct RosterEntry {
byte _ac = 0;
uint8 _food = 0;
uint8 _condition = 0;
+ uint8 _equipped[INVENTORY_COUNT] = { 0 };
+ uint8 _backpack[INVENTORY_COUNT] = { 0 };
void synchronize(Common::Serializer &s);
};
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index 608118fda9d..bc9c9e5b8b3 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -154,6 +154,7 @@ void CharacterStats::printStats() {
newLine();
newLine();
printCondition();
+ printInventory();
}
void CharacterStats::printSummary() {
@@ -221,12 +222,34 @@ void CharacterStats::printCondition() {
}
}
+void CharacterStats::printInventory() {
+ RosterEntry &re = *g_globals->_rosterEntry;
+ writeString(0, 12, STRING["stats.inventory"]);
+
+ // Print the equipped and backpack items
+ for (int i = 0; i < INVENTORY_COUNT; ++i) {
+ // Equippied item
+ writeChar(0, 13 + i, '1' + i);
+ writeChar(')');
+ _textPos.x++;
+ if (re._equipped[i])
+ writeString(STRING[Common::String::format("stats.items.%d",
+ re._equipped[i])]);
+
+ // Backpack item
+ writeChar(20, 13 + i, 'A' + i);
+ writeChar(')');
+ _textPos.x++;
+ if (re._backpack[i])
+ writeString(STRING[Common::String::format("stats.items.%d",
+ re._backpack[i])]);
+ }
+}
+
/*------------------------------------------------------------------------*/
void ViewCharacter::draw() {
assert(g_globals->_rosterEntry);
-// RosterEntry &re = *g_globals->_rosterEntry;
-
Graphics::ManagedSurface *scr = getScreen();
scr->clear();
printStats();
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/view_characters.h
index 64ee40365c4..6e4d19609ae 100644
--- a/engines/mm/mm1/views/view_characters.h
+++ b/engines/mm/mm1/views/view_characters.h
@@ -45,6 +45,8 @@ protected:
void printStats();
void printSummary();
void printCondition();
+ void printInventory();
+
public:
CharacterStats(const Common::String &name) : TextView(name) {}
~CharacterStats() {}
Commit: f35a80c6d2521004286c289418dce60b0b94c25c
https://github.com/scummvm/scummvm/commit/f35a80c6d2521004286c289418dce60b0b94c25c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Add ability to delete characters
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/utils/roster.cpp
engines/mm/mm1/utils/roster.h
engines/mm/mm1/views/view_characters.cpp
engines/mm/mm1/views/view_characters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 316bd3cb868..b546b025882 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -16,9 +16,11 @@ dialogs:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
legend2: "'ESC' TO GO BACK"
+ none: "NO AVAILABLE CHARACTERS"
view_character:
rename: "(CTRL)-'N' RE-NAME CHARACTER"
delete: "(CTRL)-'D' DELETE CHARACTER"
+ are_you_sure: " ARE YOU SURE (Y/N)? "
misc:
go_back: "'ESC' TO GO BACK"
stats:
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 36e4291dd50..870f327f8b5 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -74,7 +74,8 @@ void Events::runGame() {
void Events::processEvent(Common::Event &ev) {
switch (ev.type) {
case Common::EVENT_KEYDOWN:
- msgKeypress(KeypressMessage(ev.kbd));
+ if (ev.kbd.keycode < Common::KEYCODE_NUMLOCK)
+ msgKeypress(KeypressMessage(ev.kbd));
break;
default:
break;
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
index 73c9d56939f..45ff12cd36b 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -72,6 +72,29 @@ void RosterEntry::synchronize(Common::Serializer &s) {
s.skip(51);
}
+void RosterEntry::clear() {
+ Common::fill(_name, _name + 16, 0);
+ _sex = (Sex)0;
+ _alignment = (Alignment)0;
+ _race = (Race)0;
+ _class = (CharacterClass)0;
+ _int = _mgt = _per = _end = 0;
+ _spd = _acy = _luc = 0;
+ _level = 0;
+ _age = 0;
+ _exp = 0;
+ _sp = _spMax = 0;
+ _sp1 = 0;
+ _gems = 0;
+ _hp = _hpMax = 0;
+ _gold = 0;
+ _ac = 0;
+ _food = 0;
+ _condition = 0;
+ Common::fill(_equipped, _equipped + INVENTORY_COUNT, 0);
+ Common::fill(_backpack, _backpack + INVENTORY_COUNT, 0);
+}
+
void Roster::synchronize(Common::Serializer &s) {
for (int i = 0; i < CHARACTERS_COUNT; ++i)
_items[i].synchronize(s);
@@ -89,5 +112,21 @@ void Roster::loadDefaults() {
synchronize(s);
}
+void Roster::remove(RosterEntry *entry) {
+ entry->clear();
+
+ size_t idx = entry - _items;
+ _nums[idx] = 0;
+}
+
+bool Roster::empty() const {
+ for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
+ if (_nums[i])
+ return false;
+ }
+
+ return true;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
index d5a83f985d5..8764d4e7765 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/utils/roster.h
@@ -77,6 +77,7 @@ struct RosterEntry {
uint8 _backpack[INVENTORY_COUNT] = { 0 };
void synchronize(Common::Serializer &s);
+ void clear();
};
struct Roster {
@@ -88,8 +89,25 @@ struct Roster {
return _items[idx];
}
+ /**
+ * Synchronizes the contents of the roster
+ */
void synchronize(Common::Serializer &s);
+
+ /**
+ * Load the roster from roster.dta
+ */
void loadDefaults();
+
+ /**
+ * Deletes a character
+ */
+ void remove(RosterEntry *entry);
+
+ /**
+ * Returns true if the roster is empty
+ */
+ bool empty() const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index bc9c9e5b8b3..647cfcdda9a 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -35,6 +35,12 @@ void ViewCharacters::draw() {
int lineNum = 0;
_charIndexes.clear();
+ if (g_globals->_roster.empty()) {
+ writeString(8, 5, STRING["dialogs.view_characters.none"]);
+ escToGoBack();
+ return;
+ }
+
// Loop to print characters
for (int charNum = 0; charNum < 18; ++charNum) {
if (roster._nums[charNum]) {
@@ -72,8 +78,8 @@ bool ViewCharacters::msgKeypress(const KeypressMessage &msg) {
} else if (msg.keycode >= Common::KEYCODE_a &&
msg.keycode <= (Common::KEYCODE_a + (int)_charIndexes.size() - 1)) {
// Character selected
- g_globals->_rosterEntry = &g_globals->_roster[
- msg.keycode - Common::KEYCODE_a];
+ uint charIndex = _charIndexes[msg.keycode - Common::KEYCODE_a];
+ g_globals->_rosterEntry = &g_globals->_roster[charIndex];
addView("ViewCharacter");
}
@@ -254,14 +260,60 @@ void ViewCharacter::draw() {
scr->clear();
printStats();
- writeString(6, 21, STRING["dialogs.view_character.rename"]);
- writeString(6, 22, STRING["dialogs.view_character.delete"]);
- escToGoBack();
+ switch (_state) {
+ case DISPLAY:
+ writeString(6, 21, STRING["dialogs.view_character.rename"]);
+ writeString(6, 22, STRING["dialogs.view_character.delete"]);
+ escToGoBack();
+ break;
+
+ case RENAME:
+ break;
+
+ case DELETE:
+ writeString(6, 21, STRING["dialogs.view_character.are_you_sure"]);
+ break;
+ }
}
bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
- close();
+ if (_state != DISPLAY) {
+ redraw();
+ } else {
+ close();
+ }
+
+ _state = DISPLAY;
+ return true;
+ }
+
+ switch (_state) {
+ case DISPLAY:
+ if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_n) {
+ _state = RENAME;
+ redraw();
+ } else if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_d) {
+ _state = DELETE;
+ redraw();
+ }
+ return true;
+
+ case RENAME:
+ break;
+
+ case DELETE:
+ if (msg.keycode == Common::KEYCODE_y) {
+ // Removes the character and returns to View All Characters
+ g_globals->_roster.remove(g_globals->_rosterEntry);
+ close();
+ } else {
+ // Any other keypress returns to display mode
+ redraw();
+ }
+
+ _state = DISPLAY;
+ return true;
}
return false;
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/view_characters.h
index 6e4d19609ae..6c2abb72331 100644
--- a/engines/mm/mm1/views/view_characters.h
+++ b/engines/mm/mm1/views/view_characters.h
@@ -29,6 +29,9 @@ namespace MM {
namespace MM1 {
namespace Views {
+/**
+ * Dialog for View All Characters
+ */
class ViewCharacters : public TextView {
private:
Common::Array<uint> _charIndexes;
@@ -40,6 +43,9 @@ public:
bool msgKeypress(const KeypressMessage &msg) override;
};
+/**
+ * Base class for showing character information
+ */
class CharacterStats : public TextView {
protected:
void printStats();
@@ -52,7 +58,13 @@ public:
~CharacterStats() {}
};
+/**
+ * Dialog for showing the stats for a single character,
+ * from the View All Characters dialog
+ */
class ViewCharacter : public CharacterStats {
+ enum ViewState { DISPLAY = 0, RENAME = 1, DELETE = 2 };
+ ViewState _state = DISPLAY;
public:
ViewCharacter() : CharacterStats("ViewCharacter") {}
virtual ~ViewCharacter() {}
Commit: 4ef63fdbafda1ea5511c270b480e6b5a058f3ff9
https://github.com/scummvm/scummvm/commit/4ef63fdbafda1ea5511c270b480e6b5a058f3ff9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Implement renaming characters
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/view_characters.cpp
engines/mm/mm1/views/view_characters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b546b025882..c5eb3270536 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -21,6 +21,7 @@ dialogs:
rename: "(CTRL)-'N' RE-NAME CHARACTER"
delete: "(CTRL)-'D' DELETE CHARACTER"
are_you_sure: " ARE YOU SURE (Y/N)? "
+ name: "NAME: "
misc:
go_back: "'ESC' TO GO BACK"
stats:
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index 647cfcdda9a..e06081ac1ad 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -268,6 +268,9 @@ void ViewCharacter::draw() {
break;
case RENAME:
+ writeString(6, 21, STRING["dialogs.view_character.name"]);
+ writeString(_newName);
+ writeChar('_');
break;
case DELETE:
@@ -292,14 +295,28 @@ bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
case DISPLAY:
if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_n) {
_state = RENAME;
+ _newName = "";
redraw();
} else if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_d) {
_state = DELETE;
redraw();
}
- return true;
+ break;
case RENAME:
+ if (msg.ascii >= 32 && msg.ascii <= 127) {
+ _newName += toupper(msg.ascii);
+ redraw();
+ }
+ if (msg.keycode == Common::KEYCODE_RETURN || _newName.size() == 15) {
+ strncpy(g_globals->_rosterEntry->_name, _newName.c_str(), 16);
+ _state = DISPLAY;
+ redraw();
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
+ !_newName.empty()) {
+ _newName.deleteLastChar();
+ redraw();
+ }
break;
case DELETE:
@@ -313,10 +330,10 @@ bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
}
_state = DISPLAY;
- return true;
+ break;
}
- return false;
+ return true;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/view_characters.h
index 6c2abb72331..98f5bcb4b8f 100644
--- a/engines/mm/mm1/views/view_characters.h
+++ b/engines/mm/mm1/views/view_characters.h
@@ -65,6 +65,7 @@ public:
class ViewCharacter : public CharacterStats {
enum ViewState { DISPLAY = 0, RENAME = 1, DELETE = 2 };
ViewState _state = DISPLAY;
+ Common::String _newName;
public:
ViewCharacter() : CharacterStats("ViewCharacter") {}
virtual ~ViewCharacter() {}
Commit: 493493a4972fefc61a0f1c236eaf5c076124bf13
https://github.com/scummvm/scummvm/commit/493493a4972fefc61a0f1c236eaf5c076124bf13
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Beginnings of create characters dialog
Changed paths:
A engines/mm/mm1/views/create_characters.cpp
A engines/mm/mm1/views/create_characters.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/utils/roster.cpp
engines/mm/mm1/utils/roster.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c5eb3270536..9c0b0628f68 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1,7 +1,13 @@
dialogs:
- ready:
- 1: " ARE YOU READY? "
- 2: "THEN PRESS ENTER!"
+ create_characters:
+ title: "CREATE NEW CHARACTERS"
+ intellect: "INTELLECT...="
+ might: "MIGHT.......="
+ personality: "PERSONALITY.="
+ endurance: "ENDURANCE...="
+ speed: "SPEED.......= SELECT A CLASS"
+ accuracy: "ACCURACY....= (1-6)"
+ luck: "LUCK........= 'ENT' TO RE-ROLL"
main_menu:
title1: "MIGHT AND MAGIC"
title2: "SECRET OF THE INNER SANCTUM"
@@ -12,6 +18,9 @@ dialogs:
option3: "'#'.......GO TO TOWN"
copyright1: "COPR. 1986,1987-JON VAN CANEGHEM"
copyright2: "ALL RIGHTS RESERVED"
+ ready:
+ 1: " ARE YOU READY? "
+ 2: "THEN PRESS ENTER!"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
index 45ff12cd36b..92ab959516c 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -128,5 +128,14 @@ bool Roster::empty() const {
return true;
}
+bool Roster::full() const {
+ for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
+ if (!_nums[i])
+ return false;
+ }
+
+ return true;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
index 8764d4e7765..2a67b561158 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/utils/roster.h
@@ -108,6 +108,11 @@ struct Roster {
* Returns true if the roster is empty
*/
bool empty() const;
+
+ /**
+ * Returns true if the roster is full
+ */
+ bool full() const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
new file mode 100644
index 00000000000..55ff7b3d1a8
--- /dev/null
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/create_characters.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void CreateCharacters::NewCharacter::clear() {
+ Common::fill(_attribs, _attribs + 7, 0);
+ Common::fill(_classesAllowed, _classesAllowed + 7, 0);
+}
+
+void CreateCharacters::draw() {
+ drawTextBorder();
+
+ writeString(10, 0, STRING["dialogs.create_characters.title"]);
+ writeString(3, 5, STRING["dialogs.create_characters.intellect"]);
+ writeString(3, 7, STRING["dialogs.create_characters.might"]);
+ writeString(3, 9, STRING["dialogs.create_characters.personality"]);
+ writeString(3, 11, STRING["dialogs.create_characters.endurance"]);
+ writeString(3, 13, STRING["dialogs.create_characters.speed"]);
+ writeString(3, 15, STRING["dialogs.create_characters.accuracy"]);
+ writeString(3, 17, STRING["dialogs.create_characters.luck"]);
+
+ switch (_state) {
+ case SELECT_CLASS:
+ if (g_globals->_roster.full())
+ writeString(9, 21, STRING["dialogs.create_characters.full"]);
+ escToGoBack();
+ break;
+
+ case SELECT_RACE:
+ break;
+ }
+}
+
+void CreateCharacters::printAttributes() {
+ _textPos.y = 5;
+
+ for (int i = 0; i < 7; ++i, _textPos.y += 2) {
+ _textPos.x = 18;
+ if (_newChar._attribs[i] < 10)
+ writeChar(' ');
+ writeNumber(_newChar._attribs[i]);
+ }
+}
+
+void CreateCharacters::printClasses() {
+ if (_newChar._attribs[MIGHT] >= 12) {
+ writeString(23, 5, STRING["stats.classes.1"]);
+ _newChar._classesAllowed[KNIGHT] = true;
+ }
+ if (_newChar._attribs[MIGHT] >= 12 && _newChar._attribs[PERSONALITY] >= 12 &&
+ _newChar._attribs[ENDURANCE] >= 12) {
+ writeString(23, 7, STRING["stats.classes.2"]);
+ _newChar._classesAllowed[PALADIN] = true;
+ }
+ if (_newChar._attribs[INTELLECT] >= 12 && _newChar._attribs[ACCURACY] >= 12) {
+ writeString(23, 9, STRING["stats.classes.3"]);
+ _newChar._classesAllowed[ARCHER] = true;
+ }
+ if (_newChar._attribs[PERSONALITY] >= 12) {
+ writeString(23, 11, STRING["stats.classes.4"]);
+ _newChar._classesAllowed[CLERIC] = true;
+ }
+ if (_newChar._attribs[INTELLECT] >= 12) {
+ writeString(23, 13, STRING["stats.classes.5"]);
+ _newChar._classesAllowed[SORCERER] = true;
+ }
+ writeString(23, 15, STRING["stats.classes.6"]);
+ _newChar._classesAllowed[ROBBER] = true;
+}
+
+bool CreateCharacters::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ replaceView("MainMenu");
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/create_characters.h b/engines/mm/mm1/views/create_characters.h
new file mode 100644
index 00000000000..7e4f6458b53
--- /dev/null
+++ b/engines/mm/mm1/views/create_characters.h
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_CREATE_CHARACTERS_H
+#define MM1_VIEWS_CREATE_CHARACTERS_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class CreateCharacters : public TextView {
+ enum State {
+ SELECT_CLASS, SELECT_RACE
+ };
+ enum Attribute {
+ INTELLECT, MIGHT, PERSONALITY, ENDURANCE, SPEED,
+ ACCURACY, LUCK
+ };
+ struct NewCharacter {
+ uint8 _attribs[LUCK + 1] = { 0 };
+ bool _classesAllowed[7] = { false };
+ void clear();
+ };
+
+private:
+ State _state = SELECT_CLASS;
+ NewCharacter _newChar;
+
+ /**
+ * Displays the new character attributes
+ */
+ void printAttributes();
+
+ /**
+ * Display the available classes
+ */
+ void printClasses();
+public:
+ CreateCharacters() : TextView("CreateCharacters") {}
+ virtual ~CreateCharacters() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 4e0bc7e016b..b31d02069b4 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -23,9 +23,10 @@
#define MM1_VIEWS_DIALOGS_H
#include "mm/mm1/events.h"
-#include "mm/mm1/views/title.h"
#include "mm/mm1/views/are_you_ready.h"
+#include "mm/mm1/views/create_characters.h"
#include "mm/mm1/views/main_menu.h"
+#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
namespace MM {
@@ -35,10 +36,11 @@ namespace Views {
struct Dialogs {
private:
Views::AreYouReady _areYouReady;
+ Views::CreateCharacters _createCharacters;
Views::MainMenu _mainMenu;
Views::Title _title;
- Views::ViewCharacters _characters;
- Views::ViewCharacter _character;
+ Views::ViewCharacters _viewCharacters;
+ Views::ViewCharacter _viewCharacter;
public:
Dialogs() {}
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c16ee68ce63..9ce96ef07cc 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS := \
mm1/utils/roster.o \
mm1/utils/strings.o \
mm1/views/are_you_ready.o \
+ mm1/views/create_characters.o \
mm1/views/main_menu.o \
mm1/views/title.o \
mm1/views/text_view.o \
Commit: b0e79adf02b182bec4fb207ed7ad0cde3f714c87
https://github.com/scummvm/scummvm/commit/b0e79adf02b182bec4fb207ed7ad0cde3f714c87
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Work on Create Characters dialog
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/mm1.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/create_characters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9c0b0628f68..da5fdc1b98f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -8,6 +8,13 @@ dialogs:
speed: "SPEED.......= SELECT A CLASS"
accuracy: "ACCURACY....= (1-6)"
luck: "LUCK........= 'ENT' TO RE-ROLL"
+ class: "CLASS.="
+ race: "RACE..="
+ select_race: "SELECT A RACE"
+ select_alignment: "SELECT ALIGNMENT"
+ select_sex: "SELECT A SEX"
+ start_over: "'ESC' START OVER"
+ name: "NAME:"
main_menu:
title1: "MIGHT AND MAGIC"
title2: "SECRET OF THE INNER SANCTUM"
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index 4bd584ff39b..2c018e074e4 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -54,6 +54,9 @@ public:
int getRandomNumber(int minNumber, int maxNumber) {
return _randomSource.getRandomNumber(maxNumber - minNumber + 1) + minNumber;
}
+ int getRandomNumber(int maxNumber) {
+ return _randomSource.getRandomNumber(maxNumber);
+ }
};
extern MM1Engine *g_engine;
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 55ff7b3d1a8..375c44aadd5 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -21,16 +21,42 @@
#include "mm/mm1/views/create_characters.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
namespace Views {
void CreateCharacters::NewCharacter::clear() {
- Common::fill(_attribs, _attribs + 7, 0);
+ Common::fill(_attribs1, _attribs1 + 7, 0);
+ Common::fill(_attribs2, _attribs2 + 7, 0);
+ _class = KNIGHT;
+ _race = HUMAN;
+ _alignment = GOOD;
+ _sex = MALE;
+ _name = "";
+
Common::fill(_classesAllowed, _classesAllowed + 7, 0);
}
+void CreateCharacters::NewCharacter::reroll() {
+ clear();
+
+ // Generate attributes
+ for (int attrib = INTELLECT; attrib <= LUCK; ++attrib)
+ _attribs1[attrib] = g_engine->getRandomNumber(4, 17);
+ Common::copy(_attribs1, _attribs1 + 7, _attribs2);
+
+ // Select which classes are available
+ _classesAllowed[KNIGHT] = _attribs1[MIGHT] >= 12;
+ _classesAllowed[PALADIN] = _attribs1[MIGHT] >= 12 && _attribs1[PERSONALITY] >= 12 &&
+ _attribs1[ENDURANCE] >= 12;
+ _classesAllowed[ARCHER] = _attribs1[INTELLECT] >= 12 && _attribs1[ACCURACY] >= 12;
+ _classesAllowed[CLERIC] = _attribs1[PERSONALITY] >= 12;
+ _classesAllowed[SORCERER] = _attribs1[INTELLECT] >= 12;
+ _classesAllowed[ROBBER] = true;
+}
+
void CreateCharacters::draw() {
drawTextBorder();
@@ -42,15 +68,34 @@ void CreateCharacters::draw() {
writeString(3, 13, STRING["dialogs.create_characters.speed"]);
writeString(3, 15, STRING["dialogs.create_characters.accuracy"]);
writeString(3, 17, STRING["dialogs.create_characters.luck"]);
+ printAttributes();
switch (_state) {
case SELECT_CLASS:
+ printClasses();
if (g_globals->_roster.full())
writeString(9, 21, STRING["dialogs.create_characters.full"]);
escToGoBack();
break;
case SELECT_RACE:
+ printRaces();
+ break;
+
+ case SELECT_ALIGNMENT:
+ printAlignments();
+ break;
+
+ case SELECT_SEX:
+ printSexes();
+ break;
+
+ case SELECT_NAME:
+ printSummary(false);
+ break;
+
+ case SAVE_PROMPT:
+ printSummary(true);
break;
}
}
@@ -60,45 +105,172 @@ void CreateCharacters::printAttributes() {
for (int i = 0; i < 7; ++i, _textPos.y += 2) {
_textPos.x = 18;
- if (_newChar._attribs[i] < 10)
+ if (_newChar._attribs1[i] < 10)
writeChar(' ');
- writeNumber(_newChar._attribs[i]);
+ writeNumber(_newChar._attribs1[i]);
}
}
void CreateCharacters::printClasses() {
- if (_newChar._attribs[MIGHT] >= 12) {
+ if (_newChar._classesAllowed[KNIGHT])
writeString(23, 5, STRING["stats.classes.1"]);
- _newChar._classesAllowed[KNIGHT] = true;
- }
- if (_newChar._attribs[MIGHT] >= 12 && _newChar._attribs[PERSONALITY] >= 12 &&
- _newChar._attribs[ENDURANCE] >= 12) {
- writeString(23, 7, STRING["stats.classes.2"]);
- _newChar._classesAllowed[PALADIN] = true;
- }
- if (_newChar._attribs[INTELLECT] >= 12 && _newChar._attribs[ACCURACY] >= 12) {
- writeString(23, 9, STRING["stats.classes.3"]);
- _newChar._classesAllowed[ARCHER] = true;
- }
- if (_newChar._attribs[PERSONALITY] >= 12) {
- writeString(23, 11, STRING["stats.classes.4"]);
- _newChar._classesAllowed[CLERIC] = true;
- }
- if (_newChar._attribs[INTELLECT] >= 12) {
- writeString(23, 13, STRING["stats.classes.5"]);
- _newChar._classesAllowed[SORCERER] = true;
+ if (_newChar._classesAllowed[PALADIN])
+ writeString(23, 6, STRING["stats.classes.2"]);
+ if (_newChar._classesAllowed[ARCHER])
+ writeString(23, 7, STRING["stats.classes.3"]);
+ if (_newChar._classesAllowed[CLERIC])
+ writeString(23, 8, STRING["stats.classes.4"]);
+ if (_newChar._classesAllowed[SORCERER])
+ writeString(23, 9, STRING["stats.classes.5"]);
+
+ writeString(23, 10, STRING["stats.classes.6"]);
+}
+
+void CreateCharacters::printRaces() {
+ writeString(22, 5, STRING["dialogs.create_characters.class"]);
+ writeString(STRING[Common::String::format("stats.classes.%d", _newChar._class)]);
+
+ writeString(23, 7, STRING["stats.races.1"]);
+ writeString(23, 8, STRING["stats.races.2"]);
+ writeString(23, 9, STRING["stats.races.3"]);
+ writeString(23, 10, STRING["stats.races.4"]);
+ writeString(23, 11, STRING["stats.races.5"]);
+
+ writeString(22, 13, STRING["dialogs.create_characters.select_race"]);
+ writeChar(29, 14, '5');
+ writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
+}
+
+void CreateCharacters::printAlignments() {
+ writeString(22, 5, STRING["dialogs.create_characters.class"]);
+ writeString(STRING[Common::String::format("stats.classes.%d", _newChar._class)]);
+ writeString(22, 6, STRING["dialogs.create_characters.race"]);
+ writeString(STRING[Common::String::format("stats.races.%d", _newChar._race)]);
+
+ writeString(23, 7, STRING["stats.alignments.1"]);
+ writeString(23, 8, STRING["stats.alignments.2"]);
+ writeString(23, 9, STRING["stats.alignments.3"]);
+
+ writeString(22, 13, STRING["dialogs.create_characters.select_alignment"]);
+ writeChar(29, 14, '3');
+ writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
+}
+
+void CreateCharacters::printSexes() {
+ writeString(22, 5, STRING["dialogs.create_characters.class"]);
+ writeString(STRING[Common::String::format("stats.classes.%d", _newChar._class)]);
+ writeString(22, 6, STRING["dialogs.create_characters.race"]);
+ writeString(STRING[Common::String::format("stats.races.%d", _newChar._race)]);
+ writeString(22, 7, STRING["dialogs.create_characters.alignment"]);
+ writeString(STRING[Common::String::format("stats.alignments.%d", _newChar._alignment)]);
+
+ writeString(23, 9, STRING["stats.sex.1"]);
+ writeString(23, 10, STRING["stats.sex.2"]);
+
+ writeString(22, 12, STRING["dialogs.create_characters.select_sex"]);
+ writeChar(29, 14, '2');
+ writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
+}
+
+void CreateCharacters::printSummary(bool promptToSave) {
+ writeString(22, 5, STRING["dialogs.create_characters.class"]);
+ writeString(STRING[Common::String::format("stats.classes.%d", _newChar._class)]);
+ writeString(22, 6, STRING["dialogs.create_characters.race"]);
+ writeString(STRING[Common::String::format("stats.races.%d", _newChar._race)]);
+ writeString(22, 7, STRING["dialogs.create_characters.alignment"]);
+ writeString(STRING[Common::String::format("stats.alignments.%d", _newChar._alignment)]);
+ writeString(22, 8, STRING["dialogs.create_characters.sex"]);
+ writeString(STRING[Common::String::format("stats.sex.%d", _newChar._sex)]);
+
+ writeString(22, 11, STRING["dialogs.create_characters.name"]);
+ writeString(22, 13, _newChar._name);
+
+ if (promptToSave) {
+ writeString(22, 11, STRING["dialogs.create_characters.save_character"]);
+ writeString(26, 13, "(Y/N)?");
+ } else {
+ writeChar('_');
+ writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
}
- writeString(23, 15, STRING["stats.classes.6"]);
- _newChar._classesAllowed[ROBBER] = true;
}
bool CreateCharacters::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_RETURN) {
- replaceView("MainMenu");
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ if (_state == SELECT_CLASS) {
+ close();
+ } else {
+ _state = SELECT_CLASS;
+ redraw();
+ }
return true;
}
- return false;
+ switch (_state) {
+ case SELECT_CLASS:
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ // Re-roll attributes
+ _newChar.reroll();
+ redraw();
+ } else if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_6) {
+ if (_newChar._classesAllowed[msg.keycode - Common::KEYCODE_0] &&
+ !g_globals->_roster.full()) {
+ // Selected a valid class
+ _newChar._class = (CharacterClass)(msg.keycode - Common::KEYCODE_0);
+ _state = SELECT_RACE;
+ redraw();
+ }
+ }
+ break;
+
+ case SELECT_RACE:
+ if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_5) {
+ // Selected a valid race
+ _newChar._race = (Race)(msg.keycode - Common::KEYCODE_0);
+ _state = SELECT_ALIGNMENT;
+ redraw();
+ }
+ break;
+
+ case SELECT_ALIGNMENT:
+ if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_3) {
+ // Selected a valid alignment
+ _newChar._alignment = (Alignment)(msg.keycode - Common::KEYCODE_0);
+ _state = SELECT_SEX;
+ redraw();
+ }
+ break;
+
+ case SELECT_SEX:
+ if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_2) {
+ // Selected a valid sex
+ _newChar._sex = (Sex)(msg.keycode - Common::KEYCODE_0);
+ _state = SELECT_NAME;
+ redraw();
+ }
+ break;
+
+ case SELECT_NAME:
+ if (msg.ascii >= 32 && msg.ascii <= 127) {
+ _newChar._name += toupper(msg.ascii);
+ redraw();
+ }
+ if (msg.keycode == Common::KEYCODE_RETURN || _newChar._name.size() == 15) {
+ strncpy(g_globals->_rosterEntry->_name, _newChar._name.c_str(), 16);
+ _state = SAVE_PROMPT;
+ redraw();
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
+ !_newChar._name.empty()) {
+ _newChar._name.deleteLastChar();
+ redraw();
+ }
+ break;
+ }
+
+ return true;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/create_characters.h b/engines/mm/mm1/views/create_characters.h
index 7e4f6458b53..94ed96dc073 100644
--- a/engines/mm/mm1/views/create_characters.h
+++ b/engines/mm/mm1/views/create_characters.h
@@ -22,6 +22,7 @@
#ifndef MM1_VIEWS_CREATE_CHARACTERS_H
#define MM1_VIEWS_CREATE_CHARACTERS_H
+#include "mm/mm1/utils/roster.h"
#include "mm/mm1/views/text_view.h"
namespace MM {
@@ -30,16 +31,26 @@ namespace Views {
class CreateCharacters : public TextView {
enum State {
- SELECT_CLASS, SELECT_RACE
+ SELECT_CLASS, SELECT_RACE, SELECT_ALIGNMENT,
+ SELECT_SEX, SELECT_NAME, SAVE_PROMPT
};
enum Attribute {
INTELLECT, MIGHT, PERSONALITY, ENDURANCE, SPEED,
ACCURACY, LUCK
};
struct NewCharacter {
- uint8 _attribs[LUCK + 1] = { 0 };
+ uint8 _attribs1[LUCK + 1] = { 0 };
+ uint8 _attribs2[LUCK + 1] = { 0 };
+ CharacterClass _class = KNIGHT;
+ Race _race = HUMAN;
+ Alignment _alignment = GOOD;
+ Sex _sex = MALE;
+ Common::String _name;
+
bool _classesAllowed[7] = { false };
+
void clear();
+ void reroll();
};
private:
@@ -55,10 +66,35 @@ private:
* Display the available classes
*/
void printClasses();
+
+ /**
+ * Display the races
+ */
+ void printRaces();
+
+ /**
+ * Display the alignments
+ */
+ void printAlignments();
+
+ /**
+ * Display the sexes
+ */
+ void printSexes();
+
+ /**
+ * Display the selection summaries and either name entry
+ * or prompt to save character
+ */
+ void printSummary(bool promptToSave);
public:
CreateCharacters() : TextView("CreateCharacters") {}
virtual ~CreateCharacters() {}
+ bool msgFocus(const FocusMessage &msg) {
+ _newChar.reroll();
+ return true;
+ }
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
Commit: 3f31d825a5ec242f713ca493ce0dac6e69117112
https://github.com/scummvm/scummvm/commit/3f31d825a5ec242f713ca493ce0dac6e69117112
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Remainder of character creation
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/globals.cpp
engines/mm/mm1/mm1.h
engines/mm/mm1/utils/roster.cpp
engines/mm/mm1/utils/roster.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/create_characters.h
engines/mm/mm1/views/view_characters.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index da5fdc1b98f..0b312971643 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -5,14 +5,19 @@ dialogs:
might: "MIGHT.......="
personality: "PERSONALITY.="
endurance: "ENDURANCE...="
- speed: "SPEED.......= SELECT A CLASS"
- accuracy: "ACCURACY....= (1-6)"
- luck: "LUCK........= 'ENT' TO RE-ROLL"
+ speed: "SPEED.......="
+ accuracy: "ACCURACY....="
+ luck: "LUCK........="
class: "CLASS.="
race: "RACE..="
+ alignment: "ALGN..="
+ sex: "SEX...="
+ select_class: "SELECT CLASS"
select_race: "SELECT A RACE"
select_alignment: "SELECT ALIGNMENT"
select_sex: "SELECT A SEX"
+ save_character: "SAVE CHARACTER"
+ reroll: "'ENT' TO RE-ROLL"
start_over: "'ESC' START OVER"
name: "NAME:"
main_menu:
@@ -44,26 +49,26 @@ stats:
none: "NONE"
inventory: "-----<EQUIPPED>----------<BACKPACK>----".
classes:
- 1: "1) KNIGHT "
- 2: "2) PALADIN "
- 3: "3) ARCHER "
- 4: "4) CLERIC "
- 5: "5) SORCERER"
- 6: "6) ROBBER "
+ 1: "KNIGHT"
+ 2: "PALADIN"
+ 3: "ARCHER"
+ 4: "CLERIC"
+ 5: "SORCERER"
+ 6: "ROBBER"
races:
- 1: "1) HUMAN "
- 2: "2) ELF "
- 3: "3) DWARF "
- 4: "4) GNOME "
- 5: "5) HALF-ORC "
+ 1: "HUMAN"
+ 2: "ELF"
+ 3: "DWARF"
+ 4: "GNOME"
+ 5: "HALF-ORC"
alignments:
- 1: "1) GOOD "
- 2: "2) NEUT "
- 3: "3) EVIL "
+ 1: "GOOD"
+ 2: "NEUT"
+ 3: "EVIL"
sex:
- 1: "1) MALE "
- 2: "2) FEMALE "
- 3: "3) YES PLEASE"
+ 1: "MALE"
+ 2: "FEMALE"
+ 3: "YES PLEASE"
conditions:
good: "GOOD"
eradicated: "ERADICATED"
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 0a0c1a280da..7e3d3dd02bc 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -49,8 +49,8 @@ bool Globals::load() {
if (!_strings.load("strings_en.yml"))
return false;
- // Load default roster
- _roster.loadDefaults();
+ // Load roster
+ _roster.load();
// Load the font
_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index 2c018e074e4..1dce4bd2138 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -57,6 +57,9 @@ public:
int getRandomNumber(int maxNumber) {
return _randomSource.getRandomNumber(maxNumber);
}
+ Common::String getTargetName() const {
+ return _targetName;
+ }
};
extern MM1Engine *g_engine;
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
index 92ab959516c..0d1e411b7db 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -20,7 +20,10 @@
*/
#include "common/file.h"
+#include "common/savefile.h"
+#include "common/system.h"
#include "mm/mm1/utils/roster.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
@@ -28,7 +31,7 @@ namespace MM1 {
void RosterEntry::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
s.syncAsByte(_sex);
- s.skip(1);
+ s.syncAsByte(_field11);
s.syncAsByte(_alignment);
s.syncAsByte(_race);
s.syncAsByte(_class);
@@ -54,11 +57,11 @@ void RosterEntry::synchronize(Common::Serializer &s) {
s.syncAsUint32LE(_exp);
s.syncAsUint16LE(_sp);
s.syncAsUint16LE(_spMax);
- s.skip(1);
+ s.syncAsByte(_sp2);
s.syncAsByte(_sp1);
s.syncAsUint16LE(_gems);
s.syncAsUint16LE(_hp);
- s.skip(2);
+ s.syncAsUint16LE(_hp2);
s.syncAsUint16LE(_hpMax);
s.syncAsUint16LE(_gold);
s.skip(2);
@@ -69,6 +72,7 @@ void RosterEntry::synchronize(Common::Serializer &s) {
s.syncBytes(_equipped, INVENTORY_COUNT);
s.syncBytes(_backpack, INVENTORY_COUNT);
+ // TODO: Figure purpose of remaining unknown fields
s.skip(51);
}
@@ -84,15 +88,19 @@ void RosterEntry::clear() {
_age = 0;
_exp = 0;
_sp = _spMax = 0;
- _sp1 = 0;
+ _sp1 = _sp2 = 0;
_gems = 0;
- _hp = _hpMax = 0;
+ _hp = _hp2 = _hpMax = 0;
_gold = 0;
_ac = 0;
_food = 0;
_condition = 0;
Common::fill(_equipped, _equipped + INVENTORY_COUNT, 0);
Common::fill(_backpack, _backpack + INVENTORY_COUNT, 0);
+
+ _field11 = 0;
+ _v58 = _v59 = _v62 = _v63 = _v64 = _v65 = 0;
+ _v66 = _v67 = _v6c = _v6f = 0;
}
void Roster::synchronize(Common::Serializer &s) {
@@ -103,13 +111,34 @@ void Roster::synchronize(Common::Serializer &s) {
s.syncAsByte(_nums[i]);
}
-void Roster::loadDefaults() {
- Common::File f;
- if (!f.open("roster.dta"))
- error("Could not open roster.dta");
+void Roster::load() {
+ Common::InSaveFile *sf = g_system->getSavefileManager()->openForLoading(
+ rosterSaveName());
+
+ if (sf) {
+ Common::Serializer s(sf, nullptr);
+ synchronize(s);
+ } else {
+ Common::File f;
+ if (!f.open("roster.dta"))
+ error("Could not open roster.dta");
- Common::Serializer s(&f, nullptr);
+ Common::Serializer s(&f, nullptr);
+ synchronize(s);
+ }
+}
+
+void Roster::save() {
+ Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
+ rosterSaveName());
+ Common::Serializer s(nullptr, sf);
synchronize(s);
+ delete sf;
+}
+
+Common::String Roster::rosterSaveName() const {
+ return Common::String::format("%s-roster.dta",
+ g_engine->getTargetName().c_str());
}
void Roster::remove(RosterEntry *entry) {
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
index 2a67b561158..97dcd03e3d5 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/utils/roster.h
@@ -57,6 +57,7 @@ enum Condition {
struct RosterEntry {
char _name[16] = { 0 };
Sex _sex = MALE;
+ int _field11 = 0;
Alignment _alignment = GOOD;
Race _race = HUMAN;
CharacterClass _class = NONE;
@@ -66,9 +67,9 @@ struct RosterEntry {
uint8 _age = 0;
uint32 _exp = 0;
uint16 _sp = 0, _spMax = 0;
- uint8 _sp1 = 0;
+ uint8 _sp1 = 0, _sp2 = 0;
uint16 _gems = 0;
- uint16 _hp = 0, _hpMax = 0;
+ uint16 _hp = 0, _hp2 = 0, _hpMax = 0;
uint16 _gold = 0;
byte _ac = 0;
uint8 _food = 0;
@@ -76,11 +77,18 @@ struct RosterEntry {
uint8 _equipped[INVENTORY_COUNT] = { 0 };
uint8 _backpack[INVENTORY_COUNT] = { 0 };
+ // TODO: Figure out what these are
+ int _v58, _v59, _v62, _v63, _v64, _v65;
+ int _v66, _v67, _v6c, _v6f;
+
void synchronize(Common::Serializer &s);
void clear();
};
struct Roster {
+private:
+ Common::String rosterSaveName() const;
+public:
RosterEntry _items[CHARACTERS_COUNT];
uint8 _nums[CHARACTERS_COUNT] = { 0 };
@@ -95,9 +103,14 @@ struct Roster {
void synchronize(Common::Serializer &s);
/**
- * Load the roster from roster.dta
+ * Load the roster
+ */
+ void load();
+
+ /**
+ * Save the roster
*/
- void loadDefaults();
+ void save();
/**
* Deletes a character
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 375c44aadd5..c8240e3167f 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -57,6 +57,127 @@ void CreateCharacters::NewCharacter::reroll() {
_classesAllowed[ROBBER] = true;
}
+void CreateCharacters::NewCharacter::save() {
+ uint i = 0;
+ while (i < CHARACTERS_COUNT && g_globals->_roster._nums[i])
+ ++i;
+
+ g_globals->_roster._nums[i] = 1;
+ g_globals->_rosterEntry = &g_globals->_roster[i];
+ RosterEntry &re = *g_globals->_rosterEntry;
+ re.clear();
+
+ Common::strcpy_s(re._name, _name.c_str());
+ re._sex = _sex;
+ re._alignment = _alignment;
+ re._race = _race;
+ re._class = _class;
+ re._int = _attribs1[INTELLECT];
+ re._mgt = _attribs1[MIGHT];
+ re._per = _attribs1[PERSONALITY];
+ re._end = _attribs1[ENDURANCE];
+ re._spd = _attribs1[SPEED];
+ re._acy = _attribs1[ACCURACY];
+ re._luc = _attribs1[LUCK];
+
+ switch (_class) {
+ case KNIGHT:
+ setHP(12);
+ break;
+ case PALADIN:
+ case ARCHER:
+ setHP(10);
+ break;
+ case CLERIC:
+ setHP(8);
+ setSP(_attribs1[PERSONALITY]);
+ break;
+ case SORCERER:
+ setHP(6);
+ setSP(_attribs1[INTELLECT]);
+ break;
+ case ROBBER:
+ setHP(8);
+ re._v6c = 50;
+ break;
+ }
+
+ switch (_race) {
+ case HUMAN:
+ re._v62 = re._v63 = 70;
+ re._v66 = re._v67 = 25;
+ break;
+ case ELF:
+ re._v62 = re._v63 = 70;
+ break;
+ case DWARF:
+ re._v64 = re._v65 = 25;
+ break;
+ case GNOME:
+ re._v58 = re._v59 = 20;
+ break;
+ case HALF_ORC:
+ re._v66 = re._v67 = 50;
+ break;
+ }
+
+ re._food = 10;
+ re._backpack[0] = 1;
+ re._v6f = re._field11 ? 0x10 : 0;
+
+ g_globals->_roster.save();
+}
+
+void CreateCharacters::NewCharacter::setHP(int hp) {
+ RosterEntry &re = *g_globals->_rosterEntry;
+
+ if (_attribs1[ENDURANCE] >= 19)
+ hp += 4;
+ else if (_attribs1[ENDURANCE] >= 17)
+ hp += 3;
+ else if (_attribs1[ENDURANCE] >= 15)
+ hp += 2;
+ else if (_attribs1[ENDURANCE] >= 13)
+ hp += 1;
+ else if (_attribs1[ENDURANCE] < 5)
+ hp -= 2;
+ else if (_attribs1[ENDURANCE] < 8)
+ hp -= 1;
+
+ re._hp = re._hp2 = re._hpMax = hp;
+
+ int ac = 0;
+ if (_attribs1[SPEED] >= 19)
+ ac = 4;
+ else if (_attribs1[SPEED] >= 17)
+ ac = 3;
+ else if (_attribs1[SPEED] >= 15)
+ ac = 2;
+ if (_attribs1[SPEED] >= 13)
+ ac = 1;
+
+ re._ac = ac;
+}
+
+void CreateCharacters::NewCharacter::setSP(int amount) {
+ RosterEntry &re = *g_globals->_rosterEntry;
+
+ int level = 0;
+ if (amount >= 19)
+ level = 4;
+ else if (amount >= 17)
+ level = 3;
+ else if (amount >= 15)
+ level = 2;
+ else if (amount >= 13)
+ level = 1;
+
+ re._sp = re._spMax = level + 3;
+ re._sp1 = re._sp2 = 1;
+}
+
+/*------------------------------------------------------------------------*/
+
void CreateCharacters::draw() {
drawTextBorder();
@@ -104,7 +225,7 @@ void CreateCharacters::printAttributes() {
_textPos.y = 5;
for (int i = 0; i < 7; ++i, _textPos.y += 2) {
- _textPos.x = 18;
+ _textPos.x = 17;
if (_newChar._attribs1[i] < 10)
writeChar(' ');
writeNumber(_newChar._attribs1[i]);
@@ -112,32 +233,51 @@ void CreateCharacters::printAttributes() {
}
void CreateCharacters::printClasses() {
- if (_newChar._classesAllowed[KNIGHT])
- writeString(23, 5, STRING["stats.classes.1"]);
- if (_newChar._classesAllowed[PALADIN])
- writeString(23, 6, STRING["stats.classes.2"]);
- if (_newChar._classesAllowed[ARCHER])
- writeString(23, 7, STRING["stats.classes.3"]);
- if (_newChar._classesAllowed[CLERIC])
- writeString(23, 8, STRING["stats.classes.4"]);
- if (_newChar._classesAllowed[SORCERER])
- writeString(23, 9, STRING["stats.classes.5"]);
-
- writeString(23, 10, STRING["stats.classes.6"]);
+ if (_newChar._classesAllowed[KNIGHT]) {
+ writeString(23, 5, "1) ");
+ writeString(STRING["stats.classes.1"]);
+ }
+ if (_newChar._classesAllowed[PALADIN]) {
+ writeString(23, 6, "2) ");
+ writeString(STRING["stats.classes.2"]);
+ }
+ if (_newChar._classesAllowed[ARCHER]) {
+ writeString(23, 7, "3) ");
+ writeString(STRING["stats.classes.3"]);
+ }
+ if (_newChar._classesAllowed[CLERIC]) {
+ writeString(23, 8, "4) ");
+ writeString(STRING["stats.classes.4"]);
+ }
+ if (_newChar._classesAllowed[SORCERER]) {
+ writeString(23, 9, "5) ");
+ writeString(STRING["stats.classes.5"]);
+ }
+ writeString(23, 10, "6) ");
+ writeString(STRING["stats.classes.6"]);
+
+ writeString(22, 13, STRING["dialogs.create_characters.select_class"]);
+ writeString(26, 15, "(1-6)");
+ writeString(21, 17, STRING["dialogs.create_characters.reroll"]);
}
void CreateCharacters::printRaces() {
writeString(22, 5, STRING["dialogs.create_characters.class"]);
writeString(STRING[Common::String::format("stats.classes.%d", _newChar._class)]);
- writeString(23, 7, STRING["stats.races.1"]);
- writeString(23, 8, STRING["stats.races.2"]);
- writeString(23, 9, STRING["stats.races.3"]);
- writeString(23, 10, STRING["stats.races.4"]);
- writeString(23, 11, STRING["stats.races.5"]);
+ writeString(23, 7, "1) ");
+ writeString(STRING["stats.races.1"]);
+ writeString(23, 8, "2) ");
+ writeString(STRING["stats.races.2"]);
+ writeString(23, 9, "3) ");
+ writeString(STRING["stats.races.3"]);
+ writeString(23, 10, "4) ");
+ writeString(STRING["stats.races.4"]);
+ writeString(23, 11, "5) ");
+ writeString(STRING["stats.races.5"]);
writeString(22, 13, STRING["dialogs.create_characters.select_race"]);
- writeChar(29, 14, '5');
+ writeString(26, 15, "(1-5)");
writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
}
@@ -147,12 +287,15 @@ void CreateCharacters::printAlignments() {
writeString(22, 6, STRING["dialogs.create_characters.race"]);
writeString(STRING[Common::String::format("stats.races.%d", _newChar._race)]);
- writeString(23, 7, STRING["stats.alignments.1"]);
- writeString(23, 8, STRING["stats.alignments.2"]);
- writeString(23, 9, STRING["stats.alignments.3"]);
+ writeString(23, 8, "1) ");
+ writeString(STRING["stats.alignments.1"]);
+ writeString(23, 9, "2) ");
+ writeString(STRING["stats.alignments.2"]);
+ writeString(23, 10, "3) ");
+ writeString(STRING["stats.alignments.3"]);
- writeString(22, 13, STRING["dialogs.create_characters.select_alignment"]);
- writeChar(29, 14, '3');
+ writeString(21, 13, STRING["dialogs.create_characters.select_alignment"]);
+ writeString(26, 15, "(1-3)");
writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
}
@@ -164,11 +307,13 @@ void CreateCharacters::printSexes() {
writeString(22, 7, STRING["dialogs.create_characters.alignment"]);
writeString(STRING[Common::String::format("stats.alignments.%d", _newChar._alignment)]);
- writeString(23, 9, STRING["stats.sex.1"]);
- writeString(23, 10, STRING["stats.sex.2"]);
+ writeString(23, 9, "1) ");
+ writeString(STRING["stats.sex.1"]);
+ writeString(23, 10, "2) ");
+ writeString(STRING["stats.sex.2"]);
- writeString(22, 12, STRING["dialogs.create_characters.select_sex"]);
- writeChar(29, 14, '2');
+ writeString(23, 13, STRING["dialogs.create_characters.select_sex"]);
+ writeString(26, 15, "(1-2)");
writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
}
@@ -186,8 +331,8 @@ void CreateCharacters::printSummary(bool promptToSave) {
writeString(22, 13, _newChar._name);
if (promptToSave) {
- writeString(22, 11, STRING["dialogs.create_characters.save_character"]);
- writeString(26, 13, "(Y/N)?");
+ writeString(22, 15, STRING["dialogs.create_characters.save_character"]);
+ writeString(26, 17, "(Y/N)?");
} else {
writeChar('_');
writeString(21, 17, STRING["dialogs.create_characters.start_over"]);
@@ -200,6 +345,7 @@ bool CreateCharacters::msgKeypress(const KeypressMessage &msg) {
close();
} else {
_state = SELECT_CLASS;
+ _newChar.reroll();
redraw();
}
return true;
@@ -226,8 +372,38 @@ bool CreateCharacters::msgKeypress(const KeypressMessage &msg) {
case SELECT_RACE:
if (msg.keycode >= Common::KEYCODE_1 &&
msg.keycode <= Common::KEYCODE_5) {
- // Selected a valid race
+ // Selected a race
_newChar._race = (Race)(msg.keycode - Common::KEYCODE_0);
+
+ switch (_newChar._race) {
+ case ELF:
+ _newChar._attribs1[INTELLECT]++;
+ _newChar._attribs1[ACCURACY]++;
+ _newChar._attribs1[MIGHT]--;
+ _newChar._attribs1[ENDURANCE]--;
+ break;
+ case DWARF:
+ _newChar._attribs1[ENDURANCE]++;
+ _newChar._attribs1[LUCK]++;
+ _newChar._attribs1[INTELLECT]--;
+ _newChar._attribs1[SPEED]--;
+ break;
+ case GNOME:
+ _newChar._attribs1[LUCK] += 2;
+ _newChar._attribs1[SPEED]--;
+ _newChar._attribs1[ACCURACY]--;
+ break;
+ case HALF_ORC:
+ _newChar._attribs1[MIGHT]++;
+ _newChar._attribs1[ENDURANCE]++;
+ _newChar._attribs1[INTELLECT]--;
+ _newChar._attribs1[PERSONALITY]--;
+ _newChar._attribs1[LUCK]--;
+ break;
+ default:
+ break;
+ }
+
_state = SELECT_ALIGNMENT;
redraw();
}
@@ -259,7 +435,6 @@ bool CreateCharacters::msgKeypress(const KeypressMessage &msg) {
redraw();
}
if (msg.keycode == Common::KEYCODE_RETURN || _newChar._name.size() == 15) {
- strncpy(g_globals->_rosterEntry->_name, _newChar._name.c_str(), 16);
_state = SAVE_PROMPT;
redraw();
} else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
@@ -268,6 +443,15 @@ bool CreateCharacters::msgKeypress(const KeypressMessage &msg) {
redraw();
}
break;
+
+ case SAVE_PROMPT:
+ if (msg.keycode == Common::KEYCODE_y)
+ _newChar.save();
+
+ _state = SELECT_CLASS;
+ _newChar.reroll();
+ redraw();
+ break;
}
return true;
diff --git a/engines/mm/mm1/views/create_characters.h b/engines/mm/mm1/views/create_characters.h
index 94ed96dc073..619ea46f3f9 100644
--- a/engines/mm/mm1/views/create_characters.h
+++ b/engines/mm/mm1/views/create_characters.h
@@ -39,6 +39,10 @@ class CreateCharacters : public TextView {
ACCURACY, LUCK
};
struct NewCharacter {
+ private:
+ void setHP(int hp);
+ void setSP(int sp);
+ public:
uint8 _attribs1[LUCK + 1] = { 0 };
uint8 _attribs2[LUCK + 1] = { 0 };
CharacterClass _class = KNIGHT;
@@ -51,6 +55,7 @@ class CreateCharacters : public TextView {
void clear();
void reroll();
+ void save();
};
private:
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index e06081ac1ad..f3cc9d48698 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -53,7 +53,7 @@ void ViewCharacters::draw() {
pad_string(level, 7);
Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
- STRING[Common::String::format("stats.classes.%d", (int)re._class)].c_str() + 3 :
+ STRING[Common::String::format("stats.classes.%d", (int)re._class)] :
STRING["stats.none"];
// Form line like: A) charName...(1)L1 Knight
@@ -174,17 +174,17 @@ void CharacterStats::printSummary() {
_textPos.x++;
writeString((re._alignment >= GOOD && re._alignment <= EVIL) ?
- STRING[Common::String::format("stats.alignments.%d", re._alignment)].c_str() + 3 :
+ STRING[Common::String::format("stats.alignments.%d", re._alignment)] :
STRING["stats.none"]
);
if (re._race >= HUMAN && re._race <= HALF_ORC)
- writeString(26, 0, STRING[Common::String::format("stats.races.%d", re._race)].c_str() + 3);
+ writeString(26, 0, STRING[Common::String::format("stats.races.%d", re._race)]);
else
writeString(26, 0, STRING["stats.none"]);
if (re._class >= KNIGHT && re._class <= ROBBER)
- writeString(32, 0, STRING[Common::String::format("stats.classes.%d", re._class)].c_str() + 3);
+ writeString(32, 0, STRING[Common::String::format("stats.classes.%d", re._class)]);
else
writeString(32, 0, STRING["stats.none"]);
}
Commit: 29d4cd7a7e2e91ac3395965f3191b5d650422968
https://github.com/scummvm/scummvm/commit/29d4cd7a7e2e91ac3395965f3191b5d650422968
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Beginnings of Inn dialog
Changed paths:
A engines/mm/mm1/views/inn.cpp
A engines/mm/mm1/views/inn.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/utils/roster.cpp
engines/mm/mm1/utils/roster.h
engines/mm/mm1/views/are_you_ready.cpp
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/main_menu.cpp
engines/mm/mm1/views/view_characters.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 0b312971643..5dedb0ecaed 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -20,6 +20,12 @@ dialogs:
reroll: "'ENT' TO RE-ROLL"
start_over: "'ESC' START OVER"
name: "NAME:"
+ inn:
+ title: "(%c) INN OF "
+ to_view: "TO VIEW"
+ ctrl: "(CTRL)-"
+ add_remove: "ADD/REMOVE"
+ exit: "'X' EXIT INN"
main_menu:
title1: "MIGHT AND MAGIC"
title2: "SECRET OF THE INNER SANCTUM"
@@ -37,7 +43,6 @@ dialogs:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
legend2: "'ESC' TO GO BACK"
- none: "NO AVAILABLE CHARACTERS"
view_character:
rename: "(CTRL)-'N' RE-NAME CHARACTER"
delete: "(CTRL)-'D' DELETE CHARACTER"
@@ -45,6 +50,8 @@ dialogs:
name: "NAME: "
misc:
go_back: "'ESC' TO GO BACK"
+ no_characters: "NO AVAILABLE CHARACTERS"
+ some_characters: "AVAILABLE CHARACTERS"
stats:
none: "NONE"
inventory: "-----<EQUIPPED>----------<BACKPACK>----".
@@ -99,6 +106,12 @@ stats:
ac: "AC="
food: "FOOD="
cond: "COND="
+ towns:
+ 1: "SORPIGAL"
+ 2: "PORTSMITH"
+ 3: "ALGARY"
+ 4: "DUSK"
+ 5: "ERLIQUIN"
items:
1: "CLUB"
2: "DAGGER"
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 870f327f8b5..832ec2dcbb1 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -45,7 +45,7 @@ void Events::runGame() {
Views::Dialogs dialogsContainer; // Load up all the dialogs
// Run the game
- addView("AreYouReady");
+ addView("MainMenu");
uint currTime, nextFrameTime = 0;
_screen = new Graphics::Screen();
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 0fc7baab70c..80156ade0ef 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -35,6 +35,8 @@ public:
Roster _roster;
const Graphics::Font *_font = nullptr;
RosterEntry *_rosterEntry = nullptr;
+ int _startingTown = 0;
+ int8 _partyChars[PARTY_COUNT] = { -1, -1, -1, -1, -1, -1 };
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/utils/roster.cpp
index 0d1e411b7db..b9a0100755e 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/utils/roster.cpp
@@ -108,7 +108,7 @@ void Roster::synchronize(Common::Serializer &s) {
_items[i].synchronize(s);
for (int i = 0; i < CHARACTERS_COUNT; ++i)
- s.syncAsByte(_nums[i]);
+ s.syncAsByte(_towns[i]);
}
void Roster::load() {
@@ -145,12 +145,12 @@ void Roster::remove(RosterEntry *entry) {
entry->clear();
size_t idx = entry - _items;
- _nums[idx] = 0;
+ _towns[idx] = NO_TOWN;
}
bool Roster::empty() const {
for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
- if (_nums[i])
+ if (_towns[i])
return false;
}
@@ -159,7 +159,7 @@ bool Roster::empty() const {
bool Roster::full() const {
for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
- if (!_nums[i])
+ if (!_towns[i])
return false;
}
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/utils/roster.h
index 97dcd03e3d5..e03f0b32c56 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/utils/roster.h
@@ -29,6 +29,7 @@ namespace MM1 {
#define CHARACTERS_COUNT 18
#define INVENTORY_COUNT 6
+#define PARTY_COUNT 6
enum CharacterClass {
KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
@@ -54,6 +55,11 @@ enum Condition {
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
};
+enum Town {
+ NO_TOWN = 0, SORPIGAL = 1, PORTSMITH = 2, ALGARY = 3,
+ DUSK = 4, ERLIQUIN = 5
+};
+
struct RosterEntry {
char _name[16] = { 0 };
Sex _sex = MALE;
@@ -90,7 +96,7 @@ private:
Common::String rosterSaveName() const;
public:
RosterEntry _items[CHARACTERS_COUNT];
- uint8 _nums[CHARACTERS_COUNT] = { 0 };
+ Town _towns[CHARACTERS_COUNT] = { NO_TOWN };
RosterEntry &operator[](uint idx) {
assert(idx < CHARACTERS_COUNT);
diff --git a/engines/mm/mm1/views/are_you_ready.cpp b/engines/mm/mm1/views/are_you_ready.cpp
index 83336505d8c..6d58df8e6a1 100644
--- a/engines/mm/mm1/views/are_you_ready.cpp
+++ b/engines/mm/mm1/views/are_you_ready.cpp
@@ -21,7 +21,6 @@
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/globals.h"
-#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index c8240e3167f..c49ad0223d1 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -59,10 +59,10 @@ void CreateCharacters::NewCharacter::reroll() {
void CreateCharacters::NewCharacter::save() {
uint i = 0;
- while (i < CHARACTERS_COUNT && g_globals->_roster._nums[i])
+ while (i < CHARACTERS_COUNT && g_globals->_roster._towns[i])
++i;
- g_globals->_roster._nums[i] = 1;
+ g_globals->_roster._towns[i] = SORPIGAL;
g_globals->_rosterEntry = &g_globals->_roster[i];
RosterEntry &re = *g_globals->_rosterEntry;
re.clear();
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index b31d02069b4..e68cbd60397 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -25,6 +25,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/create_characters.h"
+#include "mm/mm1/views/inn.h"
#include "mm/mm1/views/main_menu.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
@@ -37,6 +38,7 @@ struct Dialogs {
private:
Views::AreYouReady _areYouReady;
Views::CreateCharacters _createCharacters;
+ Views::Inn _inn;
Views::MainMenu _mainMenu;
Views::Title _title;
Views::ViewCharacters _viewCharacters;
diff --git a/engines/mm/mm1/views/inn.cpp b/engines/mm/mm1/views/inn.cpp
new file mode 100644
index 00000000000..0edc21be82a
--- /dev/null
+++ b/engines/mm/mm1/views/inn.cpp
@@ -0,0 +1,96 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/inn.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+bool Inn::msgFocus(const FocusMessage &msg) {
+ // Get a list of characters in the town
+ _charNums.clear();
+ for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
+ if (g_globals->_roster._towns[i] == g_globals->_startingTown)
+ _charNums.push_back(i);
+ }
+
+ return true;
+}
+
+void Inn::draw() {
+ drawTextBorder();
+
+ writeString(10, 0, Common::String::format(
+ STRING["dialogs.inn.title"].c_str(),
+ '0' + g_globals->_startingTown));
+ writeString(STRING[Common::String::format(
+ "stats.towns.%d", g_globals->_startingTown)]);
+ escToGoBack();
+
+ if (_charNums.empty()) {
+ writeString(8, 5, STRING["dialogs.misc.no_characters"]);
+ } else {
+ writeString(10, 3, STRING["dialogs.misc.some_characters"]);
+
+ for (uint idx = 0; idx < _charNums.size(); ++idx) {
+ uint charNum = _charNums[idx];
+ RosterEntry &re = g_globals->_roster[charNum];
+
+ // Check if character in party
+ bool inParty = false;
+ for (uint i = 0; i < PARTY_COUNT && !inParty; ++i)
+ inParty = g_globals->_partyChars[i] = (int)charNum;
+
+ _textPos = (idx < 9) ? Common::Point(2, 6 + idx) :
+ Common::Point(20, 6 + idx - 9);
+
+ // Write character
+ writeChar(inParty ? '@' : ' ');
+ writeChar('A' + idx);
+ writeChar(')');
+ writeString(re._name);
+ }
+
+ Common::String range = Common::String::format("'A'-'%c' ",
+ 'A' + _charNums.size() - 1);
+ writeString(13, 19, range);
+ writeString(STRING["dialogs.inn.to_view"]);
+ writeString(6, 20, STRING["dialogs.inn.ctrl"]);
+ writeString(range);
+ writeString(STRING["dialogs.inn.add_remove"]);
+ writeString(13, 22, STRING["dialogs.inn.exit"]);
+ }
+}
+
+bool Inn::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ replaceView("MainMenu");
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/inn.h b/engines/mm/mm1/views/inn.h
new file mode 100644
index 00000000000..47963d61894
--- /dev/null
+++ b/engines/mm/mm1/views/inn.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_INN_H
+#define MM1_VIEWS_INN_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Inn : public TextView {
+private:
+ Common::Array<uint> _charNums;
+public:
+ Inn() : TextView("Inn") {}
+ virtual ~Inn() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/main_menu.cpp b/engines/mm/mm1/views/main_menu.cpp
index bec1e298dee..0af3c7aa317 100644
--- a/engines/mm/mm1/views/main_menu.cpp
+++ b/engines/mm/mm1/views/main_menu.cpp
@@ -45,17 +45,26 @@ bool MainMenu::msgKeypress(const KeypressMessage &msg) {
switch (msg.keycode) {
case Common::KEYCODE_c:
addView("CreateCharacters");
- return true;
+ break;
case Common::KEYCODE_v:
addView("ViewCharacters");
- return true;
+ break;
+
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ g_globals->_startingTown = msg.keycode - Common::KEYCODE_0;
+ replaceView("Inn");
+ break;
default:
break;
}
- return false;
+ return true;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index f3cc9d48698..36e237cb45e 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -36,20 +36,20 @@ void ViewCharacters::draw() {
_charIndexes.clear();
if (g_globals->_roster.empty()) {
- writeString(8, 5, STRING["dialogs.view_characters.none"]);
+ writeString(8, 5, STRING["dialogs.misc.no_characters"]);
escToGoBack();
return;
}
// Loop to print characters
for (int charNum = 0; charNum < 18; ++charNum) {
- if (roster._nums[charNum]) {
+ if (roster._towns[charNum]) {
const RosterEntry &re = roster[charNum];
Common::String charName = re._name;
pad_string(charName, 16, '.');
Common::String level = Common::String::format("(%d)L%d",
- roster._nums[charNum], re._level);
+ roster._towns[charNum], re._level);
pad_string(level, 7);
Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 9ce96ef07cc..e6338bfd82d 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
mm1/utils/strings.o \
mm1/views/are_you_ready.o \
mm1/views/create_characters.o \
+ mm1/views/inn.o \
mm1/views/main_menu.o \
mm1/views/title.o \
mm1/views/text_view.o \
Commit: df961b62926cd58225c4cf3f0d4739bbe45b49ad
https://github.com/scummvm/scummvm/commit/df961b62926cd58225c4cf3f0d4739bbe45b49ad
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:43+01:00
Commit Message:
MM: MM1: Finished Inn dialog
Changed paths:
A engines/mm/mm1/utils/party_array.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/globals.h
engines/mm/mm1/views/inn.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 5dedb0ecaed..ecda2212d07 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -26,6 +26,7 @@ dialogs:
ctrl: "(CTRL)-"
add_remove: "ADD/REMOVE"
exit: "'X' EXIT INN"
+ full: "*** PARTY IS FULL ***"
main_menu:
title1: "MIGHT AND MAGIC"
title2: "SECRET OF THE INNER SANCTUM"
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 80156ade0ef..3e758566af6 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -24,6 +24,7 @@
#include "graphics/font.h"
#include "mm/utils/strings_data.h"
+#include "mm/mm1/utils/party_array.h"
#include "mm/mm1/utils/roster.h"
namespace MM {
@@ -36,7 +37,7 @@ public:
const Graphics::Font *_font = nullptr;
RosterEntry *_rosterEntry = nullptr;
int _startingTown = 0;
- int8 _partyChars[PARTY_COUNT] = { -1, -1, -1, -1, -1, -1 };
+ PartyArray _partyChars;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/utils/party_array.h b/engines/mm/mm1/utils/party_array.h
new file mode 100644
index 00000000000..7b0ecbcf1e7
--- /dev/null
+++ b/engines/mm/mm1/utils/party_array.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_UTILS_PARTY_ARRAY_H
+#define MM1_UTILS_PARTY_ARRAY_H
+
+#include "common/array.h"
+
+namespace MM {
+namespace MM1 {
+
+class PartyArray : public Common::Array<uint> {
+public:
+ PartyArray() : Common::Array<uint>() {}
+
+ int indexOf(uint val) const {
+ for (uint i = 0; i < size(); ++i) {
+ if ((*this)[i] == val)
+ return i;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns true if the array contains the value
+ */
+ bool contains(uint val) {
+ return indexOf(val) != -1;
+ }
+
+ /**
+ * Removes a given item from the array
+ */
+ void remove(uint val) {
+ int idx = indexOf(val);
+ if (idx != -1)
+ remove_at(idx);
+ }
+
+ /**
+ * Adds an item to the array
+ */
+ void push_back(uint val) {
+ assert(!contains(val));
+ Common::Array<uint>::push_back(val);
+ }
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/inn.cpp b/engines/mm/mm1/views/inn.cpp
index 0edc21be82a..e407a0a0c56 100644
--- a/engines/mm/mm1/views/inn.cpp
+++ b/engines/mm/mm1/views/inn.cpp
@@ -56,16 +56,11 @@ void Inn::draw() {
uint charNum = _charNums[idx];
RosterEntry &re = g_globals->_roster[charNum];
- // Check if character in party
- bool inParty = false;
- for (uint i = 0; i < PARTY_COUNT && !inParty; ++i)
- inParty = g_globals->_partyChars[i] = (int)charNum;
-
_textPos = (idx < 9) ? Common::Point(2, 6 + idx) :
Common::Point(20, 6 + idx - 9);
// Write character
- writeChar(inParty ? '@' : ' ');
+ writeChar(g_globals->_partyChars.contains(charNum) ? '@' : ' ');
writeChar('A' + idx);
writeChar(')');
writeString(re._name);
@@ -78,14 +73,36 @@ void Inn::draw() {
writeString(6, 20, STRING["dialogs.inn.ctrl"]);
writeString(range);
writeString(STRING["dialogs.inn.add_remove"]);
- writeString(13, 22, STRING["dialogs.inn.exit"]);
+
+ if (!g_globals->_partyChars.empty())
+ writeString(13, 22, STRING["dialogs.inn.exit"]);
+ if (g_globals->_partyChars.size() == PARTY_COUNT)
+ writeString(10, 16, STRING["dialogs.inn.full"]);
}
}
bool Inn::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_RETURN) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
replaceView("MainMenu");
return true;
+ } else if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode < (Common::KeyCode)(Common::KEYCODE_a + _charNums.size())) {
+ int charNum = _charNums[msg.keycode - Common::KEYCODE_a];
+
+ if (msg.flags & Common::KBD_CTRL) {
+ // Toggle in party
+ if (g_globals->_partyChars.contains(charNum))
+ g_globals->_partyChars.remove(charNum);
+ else
+ g_globals->_partyChars.push_back(charNum);
+
+ redraw();
+
+ } else if (msg.flags == 0) {
+ // View character
+ g_globals->_rosterEntry = &g_globals->_roster[charNum];
+ addView("ViewCharacter");
+ }
}
return false;
Commit: 44488c97d60b9af2da9ad0208a68a415777a7f9a
https://github.com/scummvm/scummvm/commit/44488c97d60b9af2da9ad0208a68a415777a7f9a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:44+01:00
Commit Message:
MM: MM1: Beginnings of in-game view
Changed paths:
A engines/mm/mm1/views/game.cpp
A engines/mm/mm1/views/game.h
A engines/mm/mm1/views/game_commands.cpp
A engines/mm/mm1/views/game_commands.h
A engines/mm/mm1/views/game_messages.cpp
A engines/mm/mm1/views/game_messages.h
A engines/mm/mm1/views/game_party.cpp
A engines/mm/mm1/views/game_party.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/globals.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/inn.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ecda2212d07..3874cc79f07 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -49,6 +49,24 @@ dialogs:
delete: "(CTRL)-'D' DELETE CHARACTER"
are_you_sure: " ARE YOU SURE (Y/N)? "
name: "NAME: "
+ game:
+ commands:
+ 1: " COMMANDS"
+ 2: " "
+ 3: "[ FORWARD"
+ 4: "\ BACK"
+ 5: "] TURN"
+ 6: " LEFT"
+ 7: "^ TURN"
+ 8: " RIGHT"
+ 9: "O ORDER"
+ 10: "P PROTECT"
+ 11: "R REST"
+ 12: "S SEARCH"
+ 13: "B BASH"
+ 14: "U UNLOCK"
+ 15: "Q QUIKREF"
+ 16: "# VIEW CH"
misc:
go_back: "'ESC' TO GO BACK"
no_characters: "NO AVAILABLE CHARACTERS"
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 832ec2dcbb1..487354b759c 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -156,6 +156,12 @@ void UIElement::close() {
g_engine->popView();
}
+void UIElement::draw() {
+ for (size_t i = 0; i < _children.size(); ++i) {
+ _children[i]->draw();
+ }
+}
+
bool UIElement::tick() {
for (size_t i = 0; i < _children.size(); ++i) {
if (_children[i]->tick())
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 5fa1a2bff79..3fde0c5c2cb 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -102,7 +102,7 @@ public:
/**
* Draws the element
*/
- virtual void draw() = 0;
+ virtual void draw();
/**
* Called for game frame ticks
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 3e758566af6..5c521d80fc8 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -38,6 +38,7 @@ public:
RosterEntry *_rosterEntry = nullptr;
int _startingTown = 0;
PartyArray _partyChars;
+ RosterEntry _party[PARTY_COUNT];
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index e68cbd60397..5cde3ce9994 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -25,6 +25,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/create_characters.h"
+#include "mm/mm1/views/game.h"
#include "mm/mm1/views/inn.h"
#include "mm/mm1/views/main_menu.h"
#include "mm/mm1/views/title.h"
@@ -38,6 +39,7 @@ struct Dialogs {
private:
Views::AreYouReady _areYouReady;
Views::CreateCharacters _createCharacters;
+ Views::Game _game;
Views::Inn _inn;
Views::MainMenu _mainMenu;
Views::Title _title;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
new file mode 100644
index 00000000000..01e1361ef5a
--- /dev/null
+++ b/engines/mm/mm1/views/game.cpp
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/game.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Game::Game() : TextView("Game"),
+ _commands(this), _messages(this), _party(this) {
+}
+
+void Game::draw() {
+ // Clear the screen, and then call superclass
+ // to render the subviews within the view
+ getScreen()->clear();
+ UIElement::draw();
+}
+
+bool Game::msgKeypress(const KeypressMessage &msg) {
+ return true;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/game.h b/engines/mm/mm1/views/game.h
new file mode 100644
index 00000000000..e47c410dc8f
--- /dev/null
+++ b/engines/mm/mm1/views/game.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_GAME_H
+#define MM1_VIEWS_GAME_H
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/views/game_commands.h"
+#include "mm/mm1/views/game_messages.h"
+#include "mm/mm1/views/game_party.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Game : public TextView {
+private:
+ GameCommands _commands;
+ GameMessages _messages;
+ GameParty _party;
+public:
+ Game();
+ virtual ~Game() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/game_commands.cpp b/engines/mm/mm1/views/game_commands.cpp
new file mode 100644
index 00000000000..13903425362
--- /dev/null
+++ b/engines/mm/mm1/views/game_commands.cpp
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/game_commands.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void GameCommands::draw() {
+ for (int i = 1; i < 17; ++i)
+ writeString(31, i - 1, STRING[Common::String::format(
+ "dialogs.game.commands.%d", i)]);
+}
+
+bool GameCommands::msgKeypress(const KeypressMessage &msg) {
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/game_commands.h b/engines/mm/mm1/views/game_commands.h
new file mode 100644
index 00000000000..ba1fa637c23
--- /dev/null
+++ b/engines/mm/mm1/views/game_commands.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_GAME_COMMANDS_H
+#define MM1_VIEWS_GAME_COMMANDS_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class GameCommands : public TextView {
+public:
+ GameCommands(UIElement *owner) : TextView("GameCommands", owner) {}
+ virtual ~GameCommands() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
new file mode 100644
index 00000000000..9cf4faacace
--- /dev/null
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -0,0 +1,38 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/game_messages.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void GameMessages::draw() {
+}
+
+bool GameMessages::msgKeypress(const KeypressMessage &msg) {
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
new file mode 100644
index 00000000000..a6c102c63e0
--- /dev/null
+++ b/engines/mm/mm1/views/game_messages.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_GAME_MESSAGES_H
+#define MM1_VIEWS_GAME_MESSAGES_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class GameMessages : public TextView {
+public:
+ GameMessages(UIElement *owner) : TextView("GameMessages", owner) {}
+ virtual ~GameMessages() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/game_party.cpp b/engines/mm/mm1/views/game_party.cpp
new file mode 100644
index 00000000000..c84616ea732
--- /dev/null
+++ b/engines/mm/mm1/views/game_party.cpp
@@ -0,0 +1,38 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/game_party.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void GameParty::draw() {
+}
+
+bool GameParty::msgKeypress(const KeypressMessage &msg) {
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/game_party.h b/engines/mm/mm1/views/game_party.h
new file mode 100644
index 00000000000..c6c087489d3
--- /dev/null
+++ b/engines/mm/mm1/views/game_party.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_GAME_PARTY_H
+#define MM1_VIEWS_GAME_PARTY_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class GameParty : public TextView {
+public:
+ GameParty(UIElement *owner) : TextView("GameParty", owner) {}
+ virtual ~GameParty() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/inn.cpp b/engines/mm/mm1/views/inn.cpp
index e407a0a0c56..de0007b1c26 100644
--- a/engines/mm/mm1/views/inn.cpp
+++ b/engines/mm/mm1/views/inn.cpp
@@ -103,6 +103,16 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
g_globals->_rosterEntry = &g_globals->_roster[charNum];
addView("ViewCharacter");
}
+ } else if (msg.keycode == Common::KEYCODE_x) {
+ // Load party from selected characters
+ for (uint i = 0; i < g_globals->_partyChars.size(); ++i)
+ g_globals->_party[i] = g_globals->_roster[g_globals->_partyChars[i]];
+ for (uint i = g_globals->_partyChars.size(); i < PARTY_COUNT; ++i)
+ g_globals->_party[i].clear();
+
+ // TODO: town setup
+ // Switch to game view
+ replaceView("Game");
}
return false;
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index d30a36e0b93..68bdab15b25 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -32,6 +32,10 @@ TextView::TextView(const Common::String &name) :
UIElement(name, g_engine) {
}
+TextView::TextView(const Common::String &name, UIElement *owner) :
+ UIElement(name, owner) {
+}
+
void TextView::writeChar(char c) {
g_globals->_font->drawChar(getScreen(), c,
_textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index c14359d3e95..739c3f83947 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -70,6 +70,7 @@ protected:
void escToGoBack();
public:
TextView(const Common::String &name);
+ TextView(const Common::String &name, UIElement *owner);
virtual ~TextView() {}
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index e6338bfd82d..5308ae6c5db 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -13,6 +13,10 @@ MODULE_OBJS := \
mm1/utils/strings.o \
mm1/views/are_you_ready.o \
mm1/views/create_characters.o \
+ mm1/views/game.o \
+ mm1/views/game_commands.o \
+ mm1/views/game_messages.o \
+ mm1/views/game_party.o \
mm1/views/inn.o \
mm1/views/main_menu.o \
mm1/views/title.o \
Commit: dbd06a89d7f9dee0db84601cafa824a0c9c6b3e4
https://github.com/scummvm/scummvm/commit/dbd06a89d7f9dee0db84601cafa824a0c9c6b3e4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:44+01:00
Commit Message:
MM: XEEN: Move XeenEngine methods from out of metaengine.cpp
Changed paths:
engines/mm/metaengine.cpp
engines/mm/xeen/xeen.cpp
diff --git a/engines/mm/metaengine.cpp b/engines/mm/metaengine.cpp
index c9e39850fff..91a5aef7425 100644
--- a/engines/mm/metaengine.cpp
+++ b/engines/mm/metaengine.cpp
@@ -33,44 +33,6 @@
#define MAX_SAVES 99
-namespace MM {
-namespace Xeen {
-
-uint32 XeenEngine::getGameID() const {
- return _gameDescription->gameID;
-}
-
-uint32 XeenEngine::getSpecificGameId() const {
- uint gameId = g_vm->getGameID();
- if (gameId == GType_WorldOfXeen)
- gameId = _files->_ccNum ? GType_DarkSide : GType_Clouds;
-
- return gameId;
-}
-
-uint32 XeenEngine::getGameFeatures() const {
- return _gameDescription->features;
-}
-
-uint32 XeenEngine::getFeatures() const {
- return _gameDescription->desc.flags;
-}
-
-Common::Language XeenEngine::getLanguage() const {
- return _gameDescription->desc.language;
-}
-
-Common::Platform XeenEngine::getPlatform() const {
- return _gameDescription->desc.platform;
-}
-
-bool XeenEngine::getIsCD() const {
- return getFeatures() & ADGF_CD;
-}
-
-} // End of namespace Xeen
-} // End of namespace MM
-
class MMMetaEngine : public AdvancedMetaEngine {
public:
const char *getName() const override {
diff --git a/engines/mm/xeen/xeen.cpp b/engines/mm/xeen/xeen.cpp
index 76dc3d5c94b..063aab486c2 100644
--- a/engines/mm/xeen/xeen.cpp
+++ b/engines/mm/xeen/xeen.cpp
@@ -327,5 +327,38 @@ void XeenEngine::GUIError(const Common::U32String &msg) {
GUIErrorMessage(msg);
}
+
+uint32 XeenEngine::getGameID() const {
+ return _gameDescription->gameID;
+}
+
+uint32 XeenEngine::getSpecificGameId() const {
+ uint gameId = g_vm->getGameID();
+ if (gameId == GType_WorldOfXeen)
+ gameId = _files->_ccNum ? GType_DarkSide : GType_Clouds;
+
+ return gameId;
+}
+
+uint32 XeenEngine::getGameFeatures() const {
+ return _gameDescription->features;
+}
+
+uint32 XeenEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+Common::Language XeenEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+Common::Platform XeenEngine::getPlatform() const {
+ return _gameDescription->desc.platform;
+}
+
+bool XeenEngine::getIsCD() const {
+ return getFeatures() & ADGF_CD;
+}
+
} // End of namespace Xeen
} // End of namespace MM
Commit: 28fe2453653bb9aa773071e4a404857bc590949a
https://github.com/scummvm/scummvm/commit/28fe2453653bb9aa773071e4a404857bc590949a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:44+01:00
Commit Message:
MM: MM1: Adding keymapper set
Changed paths:
engines/mm/POTFILES
engines/mm/metaengine.cpp
engines/mm/mm1/events.h
diff --git a/engines/mm/POTFILES b/engines/mm/POTFILES
index 3aaca66720f..6831fe13fe9 100644
--- a/engines/mm/POTFILES
+++ b/engines/mm/POTFILES
@@ -1,3 +1,4 @@
engines/mm/detection.cpp
+engines/mm/metaengine.cpp
engines/mm/utils/engine_data.cpp
engines/mm/xeen/saves.cpp
diff --git a/engines/mm/metaengine.cpp b/engines/mm/metaengine.cpp
index 91a5aef7425..9bc783ca8e7 100644
--- a/engines/mm/metaengine.cpp
+++ b/engines/mm/metaengine.cpp
@@ -19,21 +19,26 @@
*
*/
-#include "mm/mm1/mm1.h"
-#include "mm/xeen/xeen.h"
-#include "mm/xeen/worldofxeen/worldofxeen.h"
-#include "mm/xeen/swordsofxeen/swordsofxeen.h"
-
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/keymap.h"
+#include "backends/keymapper/standard-actions.h"
#include "base/plugins.h"
-#include "common/savefile.h"
#include "engines/advancedDetector.h"
+#include "common/savefile.h"
#include "common/system.h"
#include "common/translation.h"
+
#include "mm/detection.h"
+#include "mm/mm1/mm1.h"
+#include "mm/xeen/xeen.h"
+#include "mm/xeen/worldofxeen/worldofxeen.h"
+#include "mm/xeen/swordsofxeen/swordsofxeen.h"
#define MAX_SAVES 99
class MMMetaEngine : public AdvancedMetaEngine {
+private:
+ Common::KeymapArray mm1InitKeymaps(const char *target) const;
public:
const char *getName() const override {
return "mm";
@@ -45,6 +50,7 @@ public:
int getMaximumSaveSlot() const override;
void removeSaveState(const char *target, int slot) const override;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
+ Common::KeymapArray initKeymaps(const char *target) const override;
};
bool MMMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -153,6 +159,104 @@ SaveStateDescriptor MMMetaEngine::querySaveMetaInfos(const char *target, int slo
return SaveStateDescriptor();
}
+Common::KeymapArray MMMetaEngine::initKeymaps(const char *target) const {
+ return mm1InitKeymaps(target);
+}
+
+Common::KeymapArray MMMetaEngine::mm1InitKeymaps(const char *target) const {
+ using namespace Common;
+ Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "griffon", "The Griffon Legend");
+ Action *act;
+
+ act = new Action(kStandardActionMoveUp, _("Up"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_FORWARDS);
+ act->addDefaultInputMapping("UP");
+ act->addDefaultInputMapping("JOY_UP");
+ engineKeyMap->addAction(act);
+
+ act = new Action(kStandardActionMoveDown, _("Down"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_BACKWARDS);
+ act->addDefaultInputMapping("DOWN");
+ act->addDefaultInputMapping("JOY_DOWN");
+ engineKeyMap->addAction(act);
+
+ act = new Action(kStandardActionMoveLeft, _("Turn Left"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_TURN_LEFT);
+ act->addDefaultInputMapping("LEFT");
+ act->addDefaultInputMapping("JOY_LEFT");
+ engineKeyMap->addAction(act);
+
+ act = new Action(kStandardActionMoveRight, _("Turn Right"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_TURN_RIGHT);
+ act->addDefaultInputMapping("RIGHT");
+ act->addDefaultInputMapping("JOY_RIGHT");
+ engineKeyMap->addAction(act);
+
+ act = new Action("STRAFE_LEFT", _("Strafe Left"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_STRAFE_LEFT);
+ act->addDefaultInputMapping("C+LEFT");
+ engineKeyMap->addAction(act);
+
+ act = new Action("STRAFE_RIGHT", _("Strafe Right"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_STRAFE_RIGHT);
+ act->addDefaultInputMapping("C+RIGHT");
+ engineKeyMap->addAction(act);
+
+ act = new Action("ORDER", _("Order Party"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_ORDER);
+ act->addDefaultInputMapping("o");
+ engineKeyMap->addAction(act);
+
+ act = new Action("PROTECT", _("Protect"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_PROTECT);
+ act->addDefaultInputMapping("p");
+ engineKeyMap->addAction(act);
+
+ act = new Action("REST", _("Rest"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_REST);
+ act->addDefaultInputMapping("r");
+ engineKeyMap->addAction(act);
+
+ act = new Action("SEARCH", _("Search"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_SEARCH);
+ act->addDefaultInputMapping("s");
+ engineKeyMap->addAction(act);
+
+ act = new Action("BASH", _("Bash"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_BASH);
+ act->addDefaultInputMapping("b");
+ engineKeyMap->addAction(act);
+
+ act = new Action("UNLOCK", _("Unlock"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_UNLOCK);
+ act->addDefaultInputMapping("u");
+ engineKeyMap->addAction(act);
+
+ act = new Action("QUICKREF", _("Quick Reference"));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_QUICKREF);
+ act->addDefaultInputMapping("x");
+ engineKeyMap->addAction(act);
+
+ const char *const PARTY_STRINGS[] = {
+ "PARTY1", "Party Member 1",
+ "PARTY2", "Party Member 2",
+ "PARTY3", "Party Member 3",
+ "PARTY4", "Party Member 4",
+ "PARTY5", "Party Member 5",
+ "PARTY6", "Party Member 6",
+ };
+ char key[2] = "1";
+ for (int i = 0; i < 6; ++i) {
+ key[0] = '1' + i;
+ act = new Action(PARTY_STRINGS[i * 2], _(PARTY_STRINGS[i * 2 + 1]));
+ act->setCustomEngineActionEvent(MM::MM1::ACTION_QUICKREF);
+ act->addDefaultInputMapping(key);
+ engineKeyMap->addAction(act);
+ }
+
+ return Keymap::arrayOf(engineKeyMap);
+}
+
#if PLUGIN_ENABLED_DYNAMIC(MM)
REGISTER_PLUGIN_DYNAMIC(MM, PLUGIN_TYPE_ENGINE, MMMetaEngine);
#else
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 3fde0c5c2cb..2ca199fd692 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -30,6 +30,29 @@
namespace MM {
namespace MM1 {
+// engine actions
+enum CustomAction {
+ ACTION_FORWARDS,
+ ACTION_BACKWARDS,
+ ACTION_TURN_LEFT,
+ ACTION_TURN_RIGHT,
+ ACTION_STRAFE_LEFT,
+ ACTION_STRAFE_RIGHT,
+ ACTION_ORDER,
+ ACTION_PROTECT,
+ ACTION_REST,
+ ACTION_SEARCH,
+ ACTION_BASH,
+ ACTION_UNLOCK,
+ ACTION_QUICKREF,
+ ACTION_VIEW_PARTY1,
+ ACTION_VIEW_PARTY2,
+ ACTION_VIEW_PARTY3,
+ ACTION_VIEW_PARTY4,
+ ACTION_VIEW_PARTY5,
+ ACTION_VIEW_PARTY6
+};
+
class Events;
struct Message {};
Commit: a6681097448bb85f181a3160eebf6fac39aa6d4a
https://github.com/scummvm/scummvm/commit/a6681097448bb85f181a3160eebf6fac39aa6d4a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:44+01:00
Commit Message:
MM: MM1: Beginnings of QuickRef dialog
Changed paths:
A engines/mm/mm1/views/quick_ref.cpp
A engines/mm/mm1/views/quick_ref.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/metaengine.cpp
engines/mm/mm1/events.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/mm1/views/view_characters.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3874cc79f07..6a2cea393a1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -37,6 +37,8 @@ dialogs:
option3: "'#'.......GO TO TOWN"
copyright1: "COPR. 1986,1987-JON VAN CANEGHEM"
copyright2: "ALL RIGHTS RESERVED"
+ quick_ref:
+ title: "# NAME HIT PTS SPELL PTS AC"
ready:
1: " ARE YOU READY? "
2: "THEN PRESS ENTER!"
diff --git a/engines/mm/metaengine.cpp b/engines/mm/metaengine.cpp
index 9bc783ca8e7..be14cf1dcb4 100644
--- a/engines/mm/metaengine.cpp
+++ b/engines/mm/metaengine.cpp
@@ -234,7 +234,7 @@ Common::KeymapArray MMMetaEngine::mm1InitKeymaps(const char *target) const {
act = new Action("QUICKREF", _("Quick Reference"));
act->setCustomEngineActionEvent(MM::MM1::ACTION_QUICKREF);
- act->addDefaultInputMapping("x");
+ act->addDefaultInputMapping("q");
engineKeyMap->addAction(act);
const char *const PARTY_STRINGS[] = {
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 487354b759c..e0d2ee4ce69 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -45,7 +45,7 @@ void Events::runGame() {
Views::Dialogs dialogsContainer; // Load up all the dialogs
// Run the game
- addView("MainMenu");
+ addView("QuickRef");
uint currTime, nextFrameTime = 0;
_screen = new Graphics::Screen();
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 5cde3ce9994..58b891652e4 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -28,6 +28,7 @@
#include "mm/mm1/views/game.h"
#include "mm/mm1/views/inn.h"
#include "mm/mm1/views/main_menu.h"
+#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
@@ -42,6 +43,7 @@ private:
Views::Game _game;
Views::Inn _inn;
Views::MainMenu _mainMenu;
+ Views::QuickRef _quickRef;
Views::Title _title;
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 01e1361ef5a..9c037b6faba 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -33,7 +33,7 @@ Game::Game() : TextView("Game"),
void Game::draw() {
// Clear the screen, and then call superclass
// to render the subviews within the view
- getScreen()->clear();
+ clearScreen();
UIElement::draw();
}
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
new file mode 100644
index 00000000000..6108c329392
--- /dev/null
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/quick_ref.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void QuickRef::draw() {
+ clearScreen();
+ writeString(STRING["dialogs.quick_ref.title"]);
+ _textPos.x = 0;
+ _textPos.y = 2;
+
+ for (uint idx = 0; idx < PARTY_COUNT; ++idx) {
+
+ }
+}
+
+bool QuickRef::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/quick_ref.h b/engines/mm/mm1/views/quick_ref.h
new file mode 100644
index 00000000000..25ed37515d8
--- /dev/null
+++ b/engines/mm/mm1/views/quick_ref.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_QUICK_REF_H
+#define MM1_VIEWS_QUICK_REF_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class QuickRef : public TextView {
+public:
+ QuickRef() : TextView("QuickRef") {}
+ virtual ~QuickRef() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 68bdab15b25..97e8ff960e3 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -78,9 +78,14 @@ void TextView::newLine() {
_textPos.y++;
}
+void TextView::clearScreen() {
+ getScreen()->clear();
+ _textPos.x = _textPos.y = 0;
+}
+
void TextView::drawTextBorder() {
Graphics::ManagedSurface *scr = getScreen();
- scr->clear();
+ clearScreen();
// Draw boxes in the four corners
scr->fillRect(Common::Rect(0, 0, FONT_SIZE * 3, FONT_SIZE * 3), 255);
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 739c3f83947..6685591121d 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -59,6 +59,11 @@ protected:
*/
void newLine();
+ /**
+ * Clear the screen
+ */
+ void clearScreen();
+
/**
* Draws a text border
*/
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index 36e237cb45e..acf36656d03 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -256,8 +256,7 @@ void CharacterStats::printInventory() {
void ViewCharacter::draw() {
assert(g_globals->_rosterEntry);
- Graphics::ManagedSurface *scr = getScreen();
- scr->clear();
+ clearScreen();
printStats();
switch (_state) {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 5308ae6c5db..19cd737d6be 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -19,6 +19,7 @@ MODULE_OBJS := \
mm1/views/game_party.o \
mm1/views/inn.o \
mm1/views/main_menu.o \
+ mm1/views/quick_ref.o \
mm1/views/title.o \
mm1/views/text_view.o \
mm1/views/view_characters.o \
Commit: d9b59041ca094a622d6f7aa4fb02c249f3c566a4
https://github.com/scummvm/scummvm/commit/d9b59041ca094a622d6f7aa4fb02c249f3c566a4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:44+01:00
Commit Message:
MM: MM1: Creating data/ folder for game state related classes
Changed paths:
A engines/mm/mm1/data/char.cpp
A engines/mm/mm1/data/char.h
A engines/mm/mm1/data/int_array.h
A engines/mm/mm1/data/roster.cpp
A engines/mm/mm1/data/roster.h
R engines/mm/mm1/utils/party_array.h
R engines/mm/mm1/utils/roster.cpp
R engines/mm/mm1/utils/roster.h
engines/mm/mm1/globals.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/create_characters.h
engines/mm/mm1/views/inn.cpp
engines/mm/mm1/views/view_characters.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/utils/roster.cpp b/engines/mm/mm1/data/char.cpp
similarity index 62%
rename from engines/mm/mm1/utils/roster.cpp
rename to engines/mm/mm1/data/char.cpp
index b9a0100755e..3bc4d91701b 100644
--- a/engines/mm/mm1/utils/roster.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -19,16 +19,13 @@
*
*/
-#include "common/file.h"
-#include "common/savefile.h"
-#include "common/system.h"
-#include "mm/mm1/utils/roster.h"
-#include "mm/mm1/mm1.h"
+#include "common/algorithm.h"
+#include "mm/mm1/data/char.h"
namespace MM {
namespace MM1 {
-void RosterEntry::synchronize(Common::Serializer &s) {
+void Character::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
s.syncAsByte(_sex);
s.syncAsByte(_field11);
@@ -76,7 +73,7 @@ void RosterEntry::synchronize(Common::Serializer &s) {
s.skip(51);
}
-void RosterEntry::clear() {
+void Character::clear() {
Common::fill(_name, _name + 16, 0);
_sex = (Sex)0;
_alignment = (Alignment)0;
@@ -103,68 +100,5 @@ void RosterEntry::clear() {
_v66 = _v67 = _v6c = _v6f = 0;
}
-void Roster::synchronize(Common::Serializer &s) {
- for (int i = 0; i < CHARACTERS_COUNT; ++i)
- _items[i].synchronize(s);
-
- for (int i = 0; i < CHARACTERS_COUNT; ++i)
- s.syncAsByte(_towns[i]);
-}
-
-void Roster::load() {
- Common::InSaveFile *sf = g_system->getSavefileManager()->openForLoading(
- rosterSaveName());
-
- if (sf) {
- Common::Serializer s(sf, nullptr);
- synchronize(s);
- } else {
- Common::File f;
- if (!f.open("roster.dta"))
- error("Could not open roster.dta");
-
- Common::Serializer s(&f, nullptr);
- synchronize(s);
- }
-}
-
-void Roster::save() {
- Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
- rosterSaveName());
- Common::Serializer s(nullptr, sf);
- synchronize(s);
- delete sf;
-}
-
-Common::String Roster::rosterSaveName() const {
- return Common::String::format("%s-roster.dta",
- g_engine->getTargetName().c_str());
-}
-
-void Roster::remove(RosterEntry *entry) {
- entry->clear();
-
- size_t idx = entry - _items;
- _towns[idx] = NO_TOWN;
-}
-
-bool Roster::empty() const {
- for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
- if (_towns[i])
- return false;
- }
-
- return true;
-}
-
-bool Roster::full() const {
- for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
- if (!_towns[i])
- return false;
- }
-
- return true;
-}
-
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/utils/roster.h b/engines/mm/mm1/data/char.h
similarity index 74%
rename from engines/mm/mm1/utils/roster.h
rename to engines/mm/mm1/data/char.h
index e03f0b32c56..ef11f0977da 100644
--- a/engines/mm/mm1/utils/roster.h
+++ b/engines/mm/mm1/data/char.h
@@ -19,17 +19,15 @@
*
*/
-#ifndef MM1_UTILS_ROSTER_H
-#define MM1_UTILS_ROSTER_H
+#ifndef MM1_UTILS_CHAR_H
+#define MM1_UTILS_CHAR_H
#include "common/serializer.h"
namespace MM {
namespace MM1 {
-#define CHARACTERS_COUNT 18
#define INVENTORY_COUNT 6
-#define PARTY_COUNT 6
enum CharacterClass {
KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
@@ -60,7 +58,7 @@ enum Town {
DUSK = 4, ERLIQUIN = 5
};
-struct RosterEntry {
+struct Character {
char _name[16] = { 0 };
Sex _sex = MALE;
int _field11 = 0;
@@ -91,49 +89,6 @@ struct RosterEntry {
void clear();
};
-struct Roster {
-private:
- Common::String rosterSaveName() const;
-public:
- RosterEntry _items[CHARACTERS_COUNT];
- Town _towns[CHARACTERS_COUNT] = { NO_TOWN };
-
- RosterEntry &operator[](uint idx) {
- assert(idx < CHARACTERS_COUNT);
- return _items[idx];
- }
-
- /**
- * Synchronizes the contents of the roster
- */
- void synchronize(Common::Serializer &s);
-
- /**
- * Load the roster
- */
- void load();
-
- /**
- * Save the roster
- */
- void save();
-
- /**
- * Deletes a character
- */
- void remove(RosterEntry *entry);
-
- /**
- * Returns true if the roster is empty
- */
- bool empty() const;
-
- /**
- * Returns true if the roster is full
- */
- bool full() const;
-};
-
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/utils/party_array.h b/engines/mm/mm1/data/int_array.h
similarity index 90%
rename from engines/mm/mm1/utils/party_array.h
rename to engines/mm/mm1/data/int_array.h
index 7b0ecbcf1e7..47d14cc5e7c 100644
--- a/engines/mm/mm1/utils/party_array.h
+++ b/engines/mm/mm1/data/int_array.h
@@ -19,17 +19,17 @@
*
*/
-#ifndef MM1_UTILS_PARTY_ARRAY_H
-#define MM1_UTILS_PARTY_ARRAY_H
+#ifndef MM1_UTILS_INT_ARRAY_H
+#define MM1_UTILS_INT_ARRAY_H
#include "common/array.h"
namespace MM {
namespace MM1 {
-class PartyArray : public Common::Array<uint> {
+class IntArray : public Common::Array<uint> {
public:
- PartyArray() : Common::Array<uint>() {}
+ IntArray() : Common::Array<uint>() {}
int indexOf(uint val) const {
for (uint i = 0; i < size(); ++i) {
diff --git a/engines/mm/mm1/data/roster.cpp b/engines/mm/mm1/data/roster.cpp
new file mode 100644
index 00000000000..f5808238d25
--- /dev/null
+++ b/engines/mm/mm1/data/roster.cpp
@@ -0,0 +1,95 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "mm/mm1/data/roster.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+
+void Roster::synchronize(Common::Serializer &s) {
+ for (int i = 0; i < ROSTER_COUNT; ++i)
+ _items[i].synchronize(s);
+
+ for (int i = 0; i < ROSTER_COUNT; ++i)
+ s.syncAsByte(_towns[i]);
+}
+
+void Roster::load() {
+ Common::InSaveFile *sf = g_system->getSavefileManager()->openForLoading(
+ rosterSaveName());
+
+ if (sf) {
+ Common::Serializer s(sf, nullptr);
+ synchronize(s);
+ } else {
+ Common::File f;
+ if (!f.open("roster.dta"))
+ error("Could not open roster.dta");
+
+ Common::Serializer s(&f, nullptr);
+ synchronize(s);
+ }
+}
+
+void Roster::save() {
+ Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
+ rosterSaveName());
+ Common::Serializer s(nullptr, sf);
+ synchronize(s);
+ delete sf;
+}
+
+Common::String Roster::rosterSaveName() const {
+ return Common::String::format("%s-roster.dta",
+ g_engine->getTargetName().c_str());
+}
+
+void Roster::remove(Character *entry) {
+ entry->clear();
+
+ size_t idx = entry - _items;
+ _towns[idx] = NO_TOWN;
+}
+
+bool Roster::empty() const {
+ for (uint i = 0; i < ROSTER_COUNT; ++i) {
+ if (_towns[i])
+ return false;
+ }
+
+ return true;
+}
+
+bool Roster::full() const {
+ for (uint i = 0; i < ROSTER_COUNT; ++i) {
+ if (!_towns[i])
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/roster.h b/engines/mm/mm1/data/roster.h
new file mode 100644
index 00000000000..bc5cef5b605
--- /dev/null
+++ b/engines/mm/mm1/data/roster.h
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_UTILS_ROSTER_H
+#define MM1_UTILS_ROSTER_H
+
+#include "common/serializer.h"
+#include "mm/mm1/data/char.h"
+
+namespace MM {
+namespace MM1 {
+
+#define ROSTER_COUNT 18
+#define PARTY_COUNT 6
+
+struct Roster {
+private:
+ Common::String rosterSaveName() const;
+public:
+ Character _items[ROSTER_COUNT];
+ Town _towns[ROSTER_COUNT] = { NO_TOWN };
+
+ Character &operator[](uint idx) {
+ assert(idx < ROSTER_COUNT);
+ return _items[idx];
+ }
+
+ /**
+ * Synchronizes the contents of the roster
+ */
+ void synchronize(Common::Serializer &s);
+
+ /**
+ * Load the roster
+ */
+ void load();
+
+ /**
+ * Save the roster
+ */
+ void save();
+
+ /**
+ * Deletes a character
+ */
+ void remove(Character *entry);
+
+ /**
+ * Returns true if the roster is empty
+ */
+ bool empty() const;
+
+ /**
+ * Returns true if the roster is full
+ */
+ bool full() const;
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 5c521d80fc8..48db6ca7b6a 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -24,8 +24,8 @@
#include "graphics/font.h"
#include "mm/utils/strings_data.h"
-#include "mm/mm1/utils/party_array.h"
-#include "mm/mm1/utils/roster.h"
+#include "mm/mm1/data/int_array.h"
+#include "mm/mm1/data/roster.h"
namespace MM {
namespace MM1 {
@@ -35,10 +35,10 @@ public:
StringsData _strings;
Roster _roster;
const Graphics::Font *_font = nullptr;
- RosterEntry *_rosterEntry = nullptr;
+ Character *_currCharacter = nullptr;
int _startingTown = 0;
- PartyArray _partyChars;
- RosterEntry _party[PARTY_COUNT];
+ IntArray _partyChars;
+ Character _party[PARTY_COUNT];
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index c49ad0223d1..2ada2f1c4de 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -59,12 +59,12 @@ void CreateCharacters::NewCharacter::reroll() {
void CreateCharacters::NewCharacter::save() {
uint i = 0;
- while (i < CHARACTERS_COUNT && g_globals->_roster._towns[i])
+ while (i < ROSTER_COUNT && g_globals->_roster._towns[i])
++i;
g_globals->_roster._towns[i] = SORPIGAL;
- g_globals->_rosterEntry = &g_globals->_roster[i];
- RosterEntry &re = *g_globals->_rosterEntry;
+ g_globals->_currCharacter = &g_globals->_roster[i];
+ Character &re = *g_globals->_currCharacter;
re.clear();
Common::strcpy_s(re._name, _name.c_str());
@@ -129,7 +129,7 @@ void CreateCharacters::NewCharacter::save() {
}
void CreateCharacters::NewCharacter::setHP(int hp) {
- RosterEntry &re = *g_globals->_rosterEntry;
+ Character &re = *g_globals->_currCharacter;
if (_attribs1[ENDURANCE] >= 19)
hp += 4;
@@ -160,7 +160,7 @@ void CreateCharacters::NewCharacter::setHP(int hp) {
}
void CreateCharacters::NewCharacter::setSP(int amount) {
- RosterEntry &re = *g_globals->_rosterEntry;
+ Character &re = *g_globals->_currCharacter;
int level = 0;
if (amount >= 19)
diff --git a/engines/mm/mm1/views/create_characters.h b/engines/mm/mm1/views/create_characters.h
index 619ea46f3f9..7f3d000cc47 100644
--- a/engines/mm/mm1/views/create_characters.h
+++ b/engines/mm/mm1/views/create_characters.h
@@ -22,7 +22,7 @@
#ifndef MM1_VIEWS_CREATE_CHARACTERS_H
#define MM1_VIEWS_CREATE_CHARACTERS_H
-#include "mm/mm1/utils/roster.h"
+#include "mm/mm1/data/roster.h"
#include "mm/mm1/views/text_view.h"
namespace MM {
diff --git a/engines/mm/mm1/views/inn.cpp b/engines/mm/mm1/views/inn.cpp
index de0007b1c26..6f7deb116e4 100644
--- a/engines/mm/mm1/views/inn.cpp
+++ b/engines/mm/mm1/views/inn.cpp
@@ -29,7 +29,7 @@ namespace Views {
bool Inn::msgFocus(const FocusMessage &msg) {
// Get a list of characters in the town
_charNums.clear();
- for (uint i = 0; i < CHARACTERS_COUNT; ++i) {
+ for (uint i = 0; i < ROSTER_COUNT; ++i) {
if (g_globals->_roster._towns[i] == g_globals->_startingTown)
_charNums.push_back(i);
}
@@ -54,7 +54,7 @@ void Inn::draw() {
for (uint idx = 0; idx < _charNums.size(); ++idx) {
uint charNum = _charNums[idx];
- RosterEntry &re = g_globals->_roster[charNum];
+ Character &re = g_globals->_roster[charNum];
_textPos = (idx < 9) ? Common::Point(2, 6 + idx) :
Common::Point(20, 6 + idx - 9);
@@ -100,7 +100,7 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
} else if (msg.flags == 0) {
// View character
- g_globals->_rosterEntry = &g_globals->_roster[charNum];
+ g_globals->_currCharacter = &g_globals->_roster[charNum];
addView("ViewCharacter");
}
} else if (msg.keycode == Common::KEYCODE_x) {
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index acf36656d03..b122fdc17c9 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -44,7 +44,7 @@ void ViewCharacters::draw() {
// Loop to print characters
for (int charNum = 0; charNum < 18; ++charNum) {
if (roster._towns[charNum]) {
- const RosterEntry &re = roster[charNum];
+ const Character &re = roster[charNum];
Common::String charName = re._name;
pad_string(charName, 16, '.');
@@ -79,7 +79,7 @@ bool ViewCharacters::msgKeypress(const KeypressMessage &msg) {
msg.keycode <= (Common::KEYCODE_a + (int)_charIndexes.size() - 1)) {
// Character selected
uint charIndex = _charIndexes[msg.keycode - Common::KEYCODE_a];
- g_globals->_rosterEntry = &g_globals->_roster[charIndex];
+ g_globals->_currCharacter = &g_globals->_roster[charIndex];
addView("ViewCharacter");
}
@@ -89,7 +89,7 @@ bool ViewCharacters::msgKeypress(const KeypressMessage &msg) {
/*------------------------------------------------------------------------*/
void CharacterStats::printStats() {
- RosterEntry &re = *g_globals->_rosterEntry;
+ Character &re = *g_globals->_currCharacter;
printSummary();
newLine();
@@ -164,7 +164,7 @@ void CharacterStats::printStats() {
}
void CharacterStats::printSummary() {
- RosterEntry &re = *g_globals->_rosterEntry;
+ Character &re = *g_globals->_currCharacter;
writeString(1, 0, re._name);
_textPos.x = 17;
@@ -190,7 +190,7 @@ void CharacterStats::printSummary() {
}
void CharacterStats::printCondition() {
- RosterEntry &re = *g_globals->_rosterEntry;
+ Character &re = *g_globals->_currCharacter;
writeString(STRING["stats.attributes.cond"]);
_textPos.x++;
int cond = re._condition;
@@ -229,7 +229,7 @@ void CharacterStats::printCondition() {
}
void CharacterStats::printInventory() {
- RosterEntry &re = *g_globals->_rosterEntry;
+ Character &re = *g_globals->_currCharacter;
writeString(0, 12, STRING["stats.inventory"]);
// Print the equipped and backpack items
@@ -255,7 +255,7 @@ void CharacterStats::printInventory() {
/*------------------------------------------------------------------------*/
void ViewCharacter::draw() {
- assert(g_globals->_rosterEntry);
+ assert(g_globals->_currCharacter);
clearScreen();
printStats();
@@ -308,7 +308,7 @@ bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
redraw();
}
if (msg.keycode == Common::KEYCODE_RETURN || _newName.size() == 15) {
- strncpy(g_globals->_rosterEntry->_name, _newName.c_str(), 16);
+ strncpy(g_globals->_currCharacter->_name, _newName.c_str(), 16);
_state = DISPLAY;
redraw();
} else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
@@ -321,7 +321,7 @@ bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
case DELETE:
if (msg.keycode == Common::KEYCODE_y) {
// Removes the character and returns to View All Characters
- g_globals->_roster.remove(g_globals->_rosterEntry);
+ g_globals->_roster.remove(g_globals->_currCharacter);
close();
} else {
// Any other keypress returns to display mode
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 19cd737d6be..52cbf83c60f 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -7,9 +7,10 @@ MODULE_OBJS := \
mm1/events.o \
mm1/globals.o \
mm1/mm1.o \
+ mm1/data/char.o \
+ mm1/data/roster.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
- mm1/utils/roster.o \
mm1/utils/strings.o \
mm1/views/are_you_ready.o \
mm1/views/create_characters.o \
Commit: be5e4e015302da1aad0fdaa01c710208b97cad29
https://github.com/scummvm/scummvm/commit/be5e4e015302da1aad0fdaa01c710208b97cad29
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:44+01:00
Commit Message:
MM: MM1: Added game state container class
Changed paths:
A engines/mm/mm1/data/game_state.h
engines/mm/mm1/data/char.h
engines/mm/mm1/data/int_array.h
engines/mm/mm1/data/roster.h
engines/mm/mm1/globals.h
engines/mm/mm1/views/inn.cpp
engines/mm/mm1/views/quick_ref.cpp
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index ef11f0977da..ce58b5a02ae 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MM1_UTILS_CHAR_H
-#define MM1_UTILS_CHAR_H
+#ifndef MM1_DATA_CHAR_H
+#define MM1_DATA_CHAR_H
#include "common/serializer.h"
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
new file mode 100644
index 00000000000..634960ce1fb
--- /dev/null
+++ b/engines/mm/mm1/data/game_state.h
@@ -0,0 +1,45 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_GAME_STATE_H
+#define MM1_DATA_GAME_STATE_H
+
+#include "common/array.h"
+#include "common/serializer.h"
+#include "mm/mm1/data/char.h"
+
+namespace MM {
+namespace MM1 {
+
+/**
+ * This acts as a container for everything in the game
+ * that is persisted to savegames
+ */
+struct GameState {
+ Common::Array<Character> _party;
+ Common::Point _mapPos;
+ int _direction = 0;
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/data/int_array.h b/engines/mm/mm1/data/int_array.h
index 47d14cc5e7c..fa604a78626 100644
--- a/engines/mm/mm1/data/int_array.h
+++ b/engines/mm/mm1/data/int_array.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MM1_UTILS_INT_ARRAY_H
-#define MM1_UTILS_INT_ARRAY_H
+#ifndef MM1_DATA_INT_ARRAY_H
+#define MM1_DATA_INT_ARRAY_H
#include "common/array.h"
diff --git a/engines/mm/mm1/data/roster.h b/engines/mm/mm1/data/roster.h
index bc5cef5b605..f5edefbdf0b 100644
--- a/engines/mm/mm1/data/roster.h
+++ b/engines/mm/mm1/data/roster.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MM1_UTILS_ROSTER_H
-#define MM1_UTILS_ROSTER_H
+#ifndef MM1_DATA_ROSTER_H
+#define MM1_DATA_ROSTER_H
#include "common/serializer.h"
#include "mm/mm1/data/char.h"
@@ -29,7 +29,6 @@ namespace MM {
namespace MM1 {
#define ROSTER_COUNT 18
-#define PARTY_COUNT 6
struct Roster {
private:
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 48db6ca7b6a..d0911a1ba88 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -24,13 +24,14 @@
#include "graphics/font.h"
#include "mm/utils/strings_data.h"
+#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/int_array.h"
#include "mm/mm1/data/roster.h"
namespace MM {
namespace MM1 {
-class Globals {
+class Globals : public GameState {
public:
StringsData _strings;
Roster _roster;
@@ -38,7 +39,6 @@ public:
Character *_currCharacter = nullptr;
int _startingTown = 0;
IntArray _partyChars;
- Character _party[PARTY_COUNT];
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/views/inn.cpp b/engines/mm/mm1/views/inn.cpp
index 6f7deb116e4..ff42c8baf72 100644
--- a/engines/mm/mm1/views/inn.cpp
+++ b/engines/mm/mm1/views/inn.cpp
@@ -76,7 +76,7 @@ void Inn::draw() {
if (!g_globals->_partyChars.empty())
writeString(13, 22, STRING["dialogs.inn.exit"]);
- if (g_globals->_partyChars.size() == PARTY_COUNT)
+ if (g_globals->_partyChars.size() == 6)
writeString(10, 16, STRING["dialogs.inn.full"]);
}
}
@@ -105,10 +105,10 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
}
} else if (msg.keycode == Common::KEYCODE_x) {
// Load party from selected characters
+ g_globals->_party.clear();
for (uint i = 0; i < g_globals->_partyChars.size(); ++i)
- g_globals->_party[i] = g_globals->_roster[g_globals->_partyChars[i]];
- for (uint i = g_globals->_partyChars.size(); i < PARTY_COUNT; ++i)
- g_globals->_party[i].clear();
+ g_globals->_party.push_back(
+ g_globals->_roster[g_globals->_partyChars[i]]);
// TODO: town setup
// Switch to game view
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 6108c329392..0dd44498c52 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -32,7 +32,7 @@ void QuickRef::draw() {
_textPos.x = 0;
_textPos.y = 2;
- for (uint idx = 0; idx < PARTY_COUNT; ++idx) {
+ for (uint idx = 0; idx < g_globals->_party.size(); ++idx) {
}
}
Commit: 1d4394a8dda8f632d232d9afd3d4432f6333c369
https://github.com/scummvm/scummvm/commit/1d4394a8dda8f632d232d9afd3d4432f6333c369
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:44+01:00
Commit Message:
MM: MM1: More implementation of QUickRef dialog
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/views/game_commands.cpp
engines/mm/mm1/views/quick_ref.cpp
engines/mm/mm1/views/quick_ref.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 6a2cea393a1..906e040c1e8 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -39,6 +39,9 @@ dialogs:
copyright2: "ALL RIGHTS RESERVED"
quick_ref:
title: "# NAME HIT PTS SPELL PTS AC"
+ food: "FOOD="
+ cond: "COND="
+ to_view: "TO VIEW"
ready:
1: " ARE YOU READY? "
2: "THEN PRESS ENTER!"
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index e0d2ee4ce69..487354b759c 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -45,7 +45,7 @@ void Events::runGame() {
Views::Dialogs dialogsContainer; // Load up all the dialogs
// Run the game
- addView("QuickRef");
+ addView("MainMenu");
uint currTime, nextFrameTime = 0;
_screen = new Graphics::Screen();
diff --git a/engines/mm/mm1/views/game_commands.cpp b/engines/mm/mm1/views/game_commands.cpp
index 13903425362..ad4e263087a 100644
--- a/engines/mm/mm1/views/game_commands.cpp
+++ b/engines/mm/mm1/views/game_commands.cpp
@@ -33,6 +33,10 @@ void GameCommands::draw() {
}
bool GameCommands::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_q) {
+ addView("QuickRef");
+ return true;
+ }
return false;
}
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 0dd44498c52..396e2027477 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -29,12 +29,56 @@ namespace Views {
void QuickRef::draw() {
clearScreen();
writeString(STRING["dialogs.quick_ref.title"]);
- _textPos.x = 0;
- _textPos.y = 2;
+ // Print list of characters, hit pts, spell pts, and ac
for (uint idx = 0; idx < g_globals->_party.size(); ++idx) {
-
+ Character &c = g_globals->_party[idx];
+
+ // Number and name
+ writeNumber(0, 2 + idx, '1' + idx);
+ _textPos.x++;
+ writeString(c._name);
+
+ // Hit points
+ _textPos.x = 18;
+ writeNumber(c._hp);
+ _textPos.x = 22;
+ writeChar('/');
+ writeNumber(c._hpMax);
+
+ // Spell points
+ _textPos.x = 28;
+ writeNumber(c._sp);
+ _textPos.x = 32;
+ writeChar('/');
+ writeNumber(c._spMax);
+
+ // AC
+ _textPos.x = 38;
+ writeNumber(c._ac);
}
+
+ // Print food and conditions of each character
+ for (uint idx = 0; idx < g_globals->_party.size(); ++idx) {
+ Character &c = g_globals->_party[idx];
+ writeNumber(0, 9 + idx, '1' + idx);
+
+ _textPos.x++;
+ writeString(STRING["dialogs.quick_ref.food"]);
+ writeNumber(c._food);
+
+ _textPos.x = 12;
+ writeString(STRING["dialogs.quick_ref.cond"]);
+ _textPos.x++;
+ printCondition();
+ }
+
+ writeString(12, 21, "'1'-'");
+ writeNumber(g_globals->_party.size());
+ writeString("' ");
+ writeString(STRING["dialogs.quick_ref.to_view"]);
+
+ escToGoBack();
}
bool QuickRef::msgKeypress(const KeypressMessage &msg) {
diff --git a/engines/mm/mm1/views/quick_ref.h b/engines/mm/mm1/views/quick_ref.h
index 25ed37515d8..2674e48f88a 100644
--- a/engines/mm/mm1/views/quick_ref.h
+++ b/engines/mm/mm1/views/quick_ref.h
@@ -22,15 +22,15 @@
#ifndef MM1_VIEWS_QUICK_REF_H
#define MM1_VIEWS_QUICK_REF_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/view_characters.h"
namespace MM {
namespace MM1 {
namespace Views {
-class QuickRef : public TextView {
+class QuickRef : public CharacterStats {
public:
- QuickRef() : TextView("QuickRef") {}
+ QuickRef() : CharacterStats("QuickRef") {}
virtual ~QuickRef() {}
void draw() override;
Commit: b81a1f3866e5bfc6dfd474dc8267b554662da018
https://github.com/scummvm/scummvm/commit/b81a1f3866e5bfc6dfd474dc8267b554662da018
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Copy mode-specific keymaps logic from Ultima engine
Changed paths:
A engines/mm/meta_engine.cpp
A engines/mm/mm1/meta_engine.cpp
A engines/mm/mm1/meta_engine.h
R engines/mm/metaengine.cpp
engines/mm/mm1/events.h
engines/mm/module.mk
diff --git a/engines/mm/metaengine.cpp b/engines/mm/meta_engine.cpp
similarity index 62%
rename from engines/mm/metaengine.cpp
rename to engines/mm/meta_engine.cpp
index be14cf1dcb4..37407732ad6 100644
--- a/engines/mm/metaengine.cpp
+++ b/engines/mm/meta_engine.cpp
@@ -38,7 +38,10 @@
class MMMetaEngine : public AdvancedMetaEngine {
private:
- Common::KeymapArray mm1InitKeymaps(const char *target) const;
+ /**
+ * Gets the game Id given a target string
+ */
+ static Common::String getGameId(const Common::String &target);
public:
const char *getName() const override {
return "mm";
@@ -160,101 +163,24 @@ SaveStateDescriptor MMMetaEngine::querySaveMetaInfos(const char *target, int slo
}
Common::KeymapArray MMMetaEngine::initKeymaps(const char *target) const {
- return mm1InitKeymaps(target);
-}
-
-Common::KeymapArray MMMetaEngine::mm1InitKeymaps(const char *target) const {
- using namespace Common;
- Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "griffon", "The Griffon Legend");
- Action *act;
-
- act = new Action(kStandardActionMoveUp, _("Up"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_FORWARDS);
- act->addDefaultInputMapping("UP");
- act->addDefaultInputMapping("JOY_UP");
- engineKeyMap->addAction(act);
-
- act = new Action(kStandardActionMoveDown, _("Down"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_BACKWARDS);
- act->addDefaultInputMapping("DOWN");
- act->addDefaultInputMapping("JOY_DOWN");
- engineKeyMap->addAction(act);
-
- act = new Action(kStandardActionMoveLeft, _("Turn Left"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_TURN_LEFT);
- act->addDefaultInputMapping("LEFT");
- act->addDefaultInputMapping("JOY_LEFT");
- engineKeyMap->addAction(act);
-
- act = new Action(kStandardActionMoveRight, _("Turn Right"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_TURN_RIGHT);
- act->addDefaultInputMapping("RIGHT");
- act->addDefaultInputMapping("JOY_RIGHT");
- engineKeyMap->addAction(act);
-
- act = new Action("STRAFE_LEFT", _("Strafe Left"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_STRAFE_LEFT);
- act->addDefaultInputMapping("C+LEFT");
- engineKeyMap->addAction(act);
-
- act = new Action("STRAFE_RIGHT", _("Strafe Right"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_STRAFE_RIGHT);
- act->addDefaultInputMapping("C+RIGHT");
- engineKeyMap->addAction(act);
+ const Common::String gameId = getGameId(target);
+ if (gameId == "mm1" || gameId == "mm1_enh")
+ return MM::MM1::MetaEngine::initKeymaps();
- act = new Action("ORDER", _("Order Party"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_ORDER);
- act->addDefaultInputMapping("o");
- engineKeyMap->addAction(act);
-
- act = new Action("PROTECT", _("Protect"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_PROTECT);
- act->addDefaultInputMapping("p");
- engineKeyMap->addAction(act);
-
- act = new Action("REST", _("Rest"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_REST);
- act->addDefaultInputMapping("r");
- engineKeyMap->addAction(act);
-
- act = new Action("SEARCH", _("Search"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_SEARCH);
- act->addDefaultInputMapping("s");
- engineKeyMap->addAction(act);
-
- act = new Action("BASH", _("Bash"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_BASH);
- act->addDefaultInputMapping("b");
- engineKeyMap->addAction(act);
-
- act = new Action("UNLOCK", _("Unlock"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_UNLOCK);
- act->addDefaultInputMapping("u");
- engineKeyMap->addAction(act);
+ return Common::KeymapArray();
+}
- act = new Action("QUICKREF", _("Quick Reference"));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_QUICKREF);
- act->addDefaultInputMapping("q");
- engineKeyMap->addAction(act);
+Common::String MMMetaEngine::getGameId(const Common::String &target) {
+ // Store a copy of the active domain
+ Common::String currDomain = ConfMan.getActiveDomainName();
- const char *const PARTY_STRINGS[] = {
- "PARTY1", "Party Member 1",
- "PARTY2", "Party Member 2",
- "PARTY3", "Party Member 3",
- "PARTY4", "Party Member 4",
- "PARTY5", "Party Member 5",
- "PARTY6", "Party Member 6",
- };
- char key[2] = "1";
- for (int i = 0; i < 6; ++i) {
- key[0] = '1' + i;
- act = new Action(PARTY_STRINGS[i * 2], _(PARTY_STRINGS[i * 2 + 1]));
- act->setCustomEngineActionEvent(MM::MM1::ACTION_QUICKREF);
- act->addDefaultInputMapping(key);
- engineKeyMap->addAction(act);
- }
+ // Switch to the given target domain and get it's game Id
+ ConfMan.setActiveDomain(target);
+ Common::String gameId = ConfMan.get("gameid");
- return Keymap::arrayOf(engineKeyMap);
+ // Switch back to the original domain and return the game Id
+ ConfMan.setActiveDomain(currDomain);
+ return gameId;
}
#if PLUGIN_ENABLED_DYNAMIC(MM)
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 2ca199fd692..46b05548fd2 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -26,38 +26,22 @@
#include "common/events.h"
#include "common/stack.h"
#include "graphics/screen.h"
+#include "mm/mm1/meta_engine.h"
namespace MM {
namespace MM1 {
-// engine actions
-enum CustomAction {
- ACTION_FORWARDS,
- ACTION_BACKWARDS,
- ACTION_TURN_LEFT,
- ACTION_TURN_RIGHT,
- ACTION_STRAFE_LEFT,
- ACTION_STRAFE_RIGHT,
- ACTION_ORDER,
- ACTION_PROTECT,
- ACTION_REST,
- ACTION_SEARCH,
- ACTION_BASH,
- ACTION_UNLOCK,
- ACTION_QUICKREF,
- ACTION_VIEW_PARTY1,
- ACTION_VIEW_PARTY2,
- ACTION_VIEW_PARTY3,
- ACTION_VIEW_PARTY4,
- ACTION_VIEW_PARTY5,
- ACTION_VIEW_PARTY6
-};
-
class Events;
struct Message {};
struct FocusMessage : public Message {};
struct UnfocusMessage : public Message {};
+struct ActionMessage : public Message {
+ KeybindingAction _action;
+ ActionMessage() : Message(), _action(KEYBIND_NONE) {}
+ ActionMessage(KeybindingAction action) : Message(),
+ _action(action) {}
+};
struct KeypressMessage : public Message, public Common::KeyState {
KeypressMessage() : Message() {}
@@ -152,6 +136,7 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
+ MESSAGE(Action);
#undef MESSAGE
};
@@ -222,6 +207,7 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
+ MESSAGE(Action);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
new file mode 100644
index 00000000000..71d69597bec
--- /dev/null
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -0,0 +1,143 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/meta_engine.h"
+#include "mm/mm1/mm1.h"
+#include "common/translation.h"
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/standard-actions.h"
+
+namespace MM {
+namespace MM1 {
+
+struct KeybindingRecord {
+ KeybindingAction _action;
+ const char *_id;
+ const char *_desc;
+ const char *_key;
+ const char *_joy;
+};
+
+static const KeybindingRecord MENU_KEYS[] = {
+ { KEYBIND_ESCAPE, "ESCPAE", "Escape", "ESC", nullptr },
+ { KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
+};
+
+static const KeybindingRecord NORMAL_KEYS[] = {
+ { KEYBIND_FORWARDS, "FORWARDS", "Forwards", "UP", nullptr },
+ { KEYBIND_BACKWARDS, "BACKWARDS", "Backwards", "DOWN", nullptr },
+ { KEYBIND_TURN_LEFT, "TURN_LEFT", "Turn Left", "LEFT", nullptr },
+ { KEYBIND_TURN_RIGHT, "TURN_RIGHT", "Turn Right", "RIGHT", nullptr },
+ { KEYBIND_STRAFE_LEFT, "STRAFE_LEFT", "Strafe Left", "C+LEFT", nullptr },
+ { KEYBIND_STRAFE_RIGHT, "STRAFE_RIGHT", "Strafe Right", "C+RIGHT", nullptr },
+
+ { KEYBIND_ORDER, "ORDER", "Reorder Party", "o", nullptr },
+ { KEYBIND_PROTECT, "PROTECT", "Protect", "p", nullptr },
+ { KEYBIND_REST, "REST", "Rest", "r", nullptr },
+ { KEYBIND_SEARCH, "SEARCH", "Search", "s", nullptr },
+ { KEYBIND_BASH, "BASH", "Bash", "b", nullptr },
+ { KEYBIND_UNLOCK, "UNLOCK", "Unlock", "u", nullptr },
+ { KEYBIND_QUICKREF, "QUICKREF", "Quick Reference", "q", nullptr },
+ { KEYBIND_VIEW_PARTY1, "PARTY1", "View Party Member 1", "1", nullptr },
+ { KEYBIND_VIEW_PARTY2, "PARTY2", "View Party Member 2", "2", nullptr },
+ { KEYBIND_VIEW_PARTY3, "PARTY3", "View Party Member 3", "3", nullptr },
+ { KEYBIND_VIEW_PARTY4, "PARTY4", "View Party Member 4", "4", nullptr },
+ { KEYBIND_VIEW_PARTY5, "PARTY5", "View Party Member 5", "5", nullptr },
+ { KEYBIND_VIEW_PARTY6, "PARTY6", "View Party Member 6", "6", nullptr },
+
+ { KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
+};
+
+static const KeybindingRecord CHEAT_KEYS[] = {
+ { KEYBIND_CHEAT_GOTO, "CHEAT-GOTO", "Goto location", "A+g", nullptr },
+ { KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
+};
+
+struct KeysRecord {
+ const char *_id;
+ const char *_desc;
+ const KeybindingRecord *_keys;
+};
+
+static const KeysRecord MENU_RECORDS[] = {
+ { "mm1", "Might and Magic 1 - Menus", MENU_KEYS },
+ { nullptr, nullptr, nullptr }
+};
+
+static const KeysRecord NORMAL_RECORDS[] = {
+ { "mm1", "Might and Magic 1", NORMAL_KEYS },
+ { "mm1_cheats", "Might and Magic 1 - Cheats", CHEAT_KEYS },
+ { nullptr, nullptr, nullptr }
+};
+
+static const KeysRecord *MODE_RECORDS[2] = {
+ MENU_RECORDS,
+ NORMAL_RECORDS
+};
+
+Common::KeymapArray MetaEngine::initKeymaps(KeybindingMode mode) {
+ Common::KeymapArray keymapArray;
+ Common::Keymap *keyMap;
+ Common::Action *act;
+ const KeysRecord *recPtr = MODE_RECORDS[mode];
+
+ for (int kCtr = 0; recPtr->_id; ++recPtr, ++kCtr) {
+ // Core keymaps
+ keyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame,
+ recPtr->_id, recPtr->_desc);
+ keymapArray.push_back(keyMap);
+
+ for (const KeybindingRecord *r = recPtr->_keys; r->_id; ++r) {
+ act = new Common::Action(r->_id, _(r->_desc));
+ act->setCustomEngineActionEvent(r->_action);
+ act->addDefaultInputMapping(r->_key);
+ if (r->_joy)
+ act->addDefaultInputMapping(r->_joy);
+
+ if (r->_action == KEYBIND_FORWARDS || r->_action == KEYBIND_BACKWARDS ||
+ r->_action == KEYBIND_TURN_LEFT || r->_action == KEYBIND_TURN_RIGHT ||
+ r->_action == KEYBIND_STRAFE_LEFT || r->_action == KEYBIND_STRAFE_RIGHT)
+ // Allow movement actions to be triggered on keyboard repeats
+ act->allowKbdRepeats();
+
+ keyMap->addAction(act);
+ }
+ }
+
+ return keymapArray;
+}
+
+void MetaEngine::setKeybindingMode(KeybindingMode mode) {
+ Common::Keymapper *const mapper = g_engine->getEventManager()->getKeymapper();
+ mapper->cleanupGameKeymaps();
+
+ Common::KeymapArray arr = initKeymaps(mode);
+
+ for (uint idx = 0; idx < arr.size(); ++idx)
+ mapper->addGameKeymap(arr[idx]);
+}
+
+void MetaEngine::executeAction(KeybindingAction keyAction) {
+ g_engine->msgAction(ActionMessage(keyAction));
+}
+
+} // End of namespace MM1
+} // End of namespace MM
diff --git a/engines/mm/mm1/meta_engine.h b/engines/mm/mm1/meta_engine.h
new file mode 100644
index 00000000000..34a461d1bb0
--- /dev/null
+++ b/engines/mm/mm1/meta_engine.h
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_MM1_META_ENGINE
+#define MM_MM1_META_ENGINE
+
+#include "backends/keymapper/keymapper.h"
+
+namespace MM {
+namespace MM1 {
+
+enum KeybindingAction {
+ KEYBIND_ESCAPE,
+
+ KEYBIND_FORWARDS,
+ KEYBIND_BACKWARDS,
+ KEYBIND_TURN_LEFT,
+ KEYBIND_TURN_RIGHT,
+ KEYBIND_STRAFE_LEFT,
+ KEYBIND_STRAFE_RIGHT,
+ KEYBIND_ORDER,
+ KEYBIND_PROTECT,
+ KEYBIND_REST,
+ KEYBIND_SEARCH,
+ KEYBIND_BASH,
+ KEYBIND_UNLOCK,
+ KEYBIND_QUICKREF,
+ KEYBIND_VIEW_PARTY1,
+ KEYBIND_VIEW_PARTY2,
+ KEYBIND_VIEW_PARTY3,
+ KEYBIND_VIEW_PARTY4,
+ KEYBIND_VIEW_PARTY5,
+ KEYBIND_VIEW_PARTY6,
+
+ KEYBIND_CHEAT_COLLISIONS, KEYBIND_CHEAT_DESTROY,
+ KEYBIND_CHEAT_DESTROY_CREATURES, KEYBIND_CHEAT_EQUIPMENT,
+ KEYBIND_CHEAT_FLEE, KEYBIND_CHEAT_GOTO, KEYBIND_CHEAT_HELP,
+ KEYBIND_CHEAT_ITEMS, KEYBIND_CHEAT_KARMA, KEYBIND_CHEAT_LEAVE,
+ KEYBIND_CHEAT_MIXTURES, KEYBIND_CHEAT_NO_COMBAT,
+ KEYBIND_CHEAT_OVERHEAD, KEYBIND_CHEAT_PARTY, KEYBIND_CHEAT_REAGENTS,
+ KEYBIND_CHEAT_STATS, KEYBIND_CHEAT_TRANSPORT, KEYBIND_CHEAT_UP,
+ KEYBIND_CHEAT_DOWN, KEYBIND_CHEAT_VIRTUE, KEYBIND_CHEAT_WIND,
+
+ KEYBIND_NONE
+};
+
+enum KeybindingMode {
+ KBMODE_MENUS, ///< Keys for when showing menus
+ KBMODE_NORMAL, ///< Keys available when normal in-game
+ KBMODE_COMBAT ///< Keys when in combat mode
+};
+
+class MetaEngine {
+public:
+ /**
+ * Initialize keymaps
+ */
+ static Common::KeymapArray initKeymaps(KeybindingMode mode = KBMODE_MENUS);
+
+ /**
+ * Execute an engine keymap action
+ */
+ static void executeAction(KeybindingAction keyAction);
+
+ /**
+ * Sets the current set of actions which are active
+ */
+ static void setKeybindingMode(KeybindingMode mode);
+};
+
+} // End of namespace MM1
+} // End of namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 52cbf83c60f..5c2f9ba3ca7 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -1,11 +1,12 @@
MODULE := engines/mm
MODULE_OBJS := \
- metaengine.o \
+ meta_engine.o \
utils/engine_data.o \
utils/strings_data.o \
mm1/events.o \
mm1/globals.o \
+ mm1/meta_engine.o \
mm1/mm1.o \
mm1/data/char.o \
mm1/data/roster.o \
Commit: 9eae42cca443d7d59ab215c005dbbc26b1b3f224
https://github.com/scummvm/scummvm/commit/9eae42cca443d7d59ab215c005dbbc26b1b3f224
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Hook up QuickRef dialog display to keybinder action
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game.h
engines/mm/mm1/views/game_commands.cpp
engines/mm/mm1/views/game_commands.h
engines/mm/mm1/views/quick_ref.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 906e040c1e8..2a2d6b0bd9b 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -39,8 +39,7 @@ dialogs:
copyright2: "ALL RIGHTS RESERVED"
quick_ref:
title: "# NAME HIT PTS SPELL PTS AC"
- food: "FOOD="
- cond: "COND="
+ food: "FOOD= "
to_view: "TO VIEW"
ready:
1: " ARE YOU READY? "
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 487354b759c..667c439f324 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -77,6 +77,9 @@ void Events::processEvent(Common::Event &ev) {
if (ev.kbd.keycode < Common::KEYCODE_NUMLOCK)
msgKeypress(KeypressMessage(ev.kbd));
break;
+ case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
+ msgAction(ActionMessage((KeybindingAction)ev.customType));
+ break;
default:
break;
}
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 9c037b6faba..458dafcecab 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/views/game.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/meta_engine.h"
namespace MM {
namespace MM1 {
@@ -30,6 +31,16 @@ Game::Game() : TextView("Game"),
_commands(this), _messages(this), _party(this) {
}
+bool Game::msgFocus(const FocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_NORMAL);
+ return true;
+}
+
+bool Game::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return true;
+}
+
void Game::draw() {
// Clear the screen, and then call superclass
// to render the subviews within the view
diff --git a/engines/mm/mm1/views/game.h b/engines/mm/mm1/views/game.h
index e47c410dc8f..5da37c65a4b 100644
--- a/engines/mm/mm1/views/game.h
+++ b/engines/mm/mm1/views/game.h
@@ -40,6 +40,8 @@ public:
Game();
virtual ~Game() {}
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
diff --git a/engines/mm/mm1/views/game_commands.cpp b/engines/mm/mm1/views/game_commands.cpp
index ad4e263087a..897d3b473a7 100644
--- a/engines/mm/mm1/views/game_commands.cpp
+++ b/engines/mm/mm1/views/game_commands.cpp
@@ -32,12 +32,12 @@ void GameCommands::draw() {
"dialogs.game.commands.%d", i)]);
}
-bool GameCommands::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_q) {
+bool GameCommands::msgAction(const ActionMessage &msg) {
+ switch (msg._action) {
+ case KEYBIND_QUICKREF:
addView("QuickRef");
return true;
}
- return false;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/game_commands.h b/engines/mm/mm1/views/game_commands.h
index ba1fa637c23..88b838aa175 100644
--- a/engines/mm/mm1/views/game_commands.h
+++ b/engines/mm/mm1/views/game_commands.h
@@ -34,7 +34,7 @@ public:
virtual ~GameCommands() {}
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
};
} // namespace Views
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 396e2027477..67dda154b22 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -35,7 +35,7 @@ void QuickRef::draw() {
Character &c = g_globals->_party[idx];
// Number and name
- writeNumber(0, 2 + idx, '1' + idx);
+ writeNumber(0, 2 + idx, idx + 1);
_textPos.x++;
writeString(c._name);
@@ -61,15 +61,14 @@ void QuickRef::draw() {
// Print food and conditions of each character
for (uint idx = 0; idx < g_globals->_party.size(); ++idx) {
Character &c = g_globals->_party[idx];
- writeNumber(0, 9 + idx, '1' + idx);
+ g_globals->_currCharacter = &c;
+ writeNumber(0, 9 + idx, idx + 1);
_textPos.x++;
writeString(STRING["dialogs.quick_ref.food"]);
writeNumber(c._food);
_textPos.x = 12;
- writeString(STRING["dialogs.quick_ref.cond"]);
- _textPos.x++;
printCondition();
}
Commit: bb15af5dd813cf7cb30e59e44d6b27992b0ea27f
https://github.com/scummvm/scummvm/commit/bb15af5dd813cf7cb30e59e44d6b27992b0ea27f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Handle QuickRef action inside QuickRef view itself
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views/game_commands.cpp
engines/mm/mm1/views/game_commands.h
engines/mm/mm1/views/quick_ref.cpp
engines/mm/mm1/views/quick_ref.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 667c439f324..ce033bd266c 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -203,5 +203,9 @@ void UIElement::addView(const Common::String &name) {
g_events->addView(name);
}
+void UIElement::addView() {
+ g_events->addView(this);
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 46b05548fd2..4808c246124 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -98,6 +98,7 @@ public:
*/
void addView(UIElement *ui);
void addView(const Common::String &name);
+ void addView();
/**
* Returns the game view
@@ -207,7 +208,6 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
- MESSAGE(Action);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/views/game_commands.cpp b/engines/mm/mm1/views/game_commands.cpp
index 897d3b473a7..de8cf0e9a04 100644
--- a/engines/mm/mm1/views/game_commands.cpp
+++ b/engines/mm/mm1/views/game_commands.cpp
@@ -32,14 +32,6 @@ void GameCommands::draw() {
"dialogs.game.commands.%d", i)]);
}
-bool GameCommands::msgAction(const ActionMessage &msg) {
- switch (msg._action) {
- case KEYBIND_QUICKREF:
- addView("QuickRef");
- return true;
- }
-}
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_commands.h b/engines/mm/mm1/views/game_commands.h
index 88b838aa175..f539b736982 100644
--- a/engines/mm/mm1/views/game_commands.h
+++ b/engines/mm/mm1/views/game_commands.h
@@ -34,7 +34,6 @@ public:
virtual ~GameCommands() {}
void draw() override;
- bool msgAction(const ActionMessage &msg) override;
};
} // namespace Views
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 67dda154b22..7dfe5d4033e 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -89,6 +89,18 @@ bool QuickRef::msgKeypress(const KeypressMessage &msg) {
return false;
}
+bool QuickRef::msgAction(const ActionMessage &msg) {
+ switch (msg._action) {
+ case KEYBIND_QUICKREF:
+ addView();
+ return true;
+ }
+
+ return false;
+}
+
+
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/quick_ref.h b/engines/mm/mm1/views/quick_ref.h
index 2674e48f88a..fae67baacf7 100644
--- a/engines/mm/mm1/views/quick_ref.h
+++ b/engines/mm/mm1/views/quick_ref.h
@@ -35,6 +35,7 @@ public:
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
};
} // namespace Views
Commit: ffcda769b3c3cb07fd837697d9ba04745db20c05
https://github.com/scummvm/scummvm/commit/ffcda769b3c3cb07fd837697d9ba04745db20c05
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Hook up action for viewing party members
Changed paths:
engines/mm/mm1/views/view_characters.cpp
engines/mm/mm1/views/view_characters.h
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index b122fdc17c9..057b912d05f 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -335,6 +335,18 @@ bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
return true;
}
+bool ViewCharacter::msgAction(const ActionMessage &msg) {
+ if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ g_globals->_currCharacter = &g_globals->_party[
+ msg._action - KEYBIND_VIEW_PARTY1];
+ addView();
+ return true;
+ }
+
+ return false;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/view_characters.h
index 98f5bcb4b8f..ddf232ec309 100644
--- a/engines/mm/mm1/views/view_characters.h
+++ b/engines/mm/mm1/views/view_characters.h
@@ -59,8 +59,7 @@ public:
};
/**
- * Dialog for showing the stats for a single character,
- * from the View All Characters dialog
+ * Dialog for showing the stats for a single character.
*/
class ViewCharacter : public CharacterStats {
enum ViewState { DISPLAY = 0, RENAME = 1, DELETE = 2 };
@@ -72,6 +71,7 @@ public:
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
};
Commit: 3ad99de58053783bd1e841b6ea14e906504c077f
https://github.com/scummvm/scummvm/commit/3ad99de58053783bd1e841b6ea14e906504c077f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Beginnings of Protect dialog
Changed paths:
A engines/mm/mm1/views/protect.cpp
A engines/mm/mm1/views/protect.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/game_state.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 2a2d6b0bd9b..d64e37b937f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -37,6 +37,27 @@ dialogs:
option3: "'#'.......GO TO TOWN"
copyright1: "COPR. 1986,1987-JON VAN CANEGHEM"
copyright2: "ALL RIGHTS RESERVED"
+ protect:
+ title: "PROTECT: SPELLS CURRENTLY ACTIVE"
+ protection: "PROTECTION FROM"
+ 1: 'FEAR"
+ 2: "COLD"
+ 3: "FIRE"
+ 4: "POISON"
+ 5: "ACID"
+ 6: "ELEC"
+ 7: "MAGIC"
+ 8: "LIGHT ("
+ 9: "LEATHER SKIN"
+ 10: "LEVITATE"
+ 11: "WALK ON WATER"
+ 12: "GUARD DOG"
+ 13: "PSYCHIC PROTECTION"
+ 14: "BLESS"
+ 15: "INVISIBILITY"
+ 16: "SHIELD"
+ 17: "POWER SHIELD"
+ 18: "*** CURSED -"
quick_ref:
title: "# NAME HIT PTS SPELL PTS AC"
food: "FOOD= "
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index 634960ce1fb..d902dad301c 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -35,6 +35,7 @@ namespace MM1 {
*/
struct GameState {
Common::Array<Character> _party;
+ Common::Array<uint> _activeSpells;
Common::Point _mapPos;
int _direction = 0;
};
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 58b891652e4..3587bed4b6e 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -28,6 +28,7 @@
#include "mm/mm1/views/game.h"
#include "mm/mm1/views/inn.h"
#include "mm/mm1/views/main_menu.h"
+#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
@@ -43,6 +44,7 @@ private:
Views::Game _game;
Views::Inn _inn;
Views::MainMenu _mainMenu;
+ Views::Protect _protect;
Views::QuickRef _quickRef;
Views::Title _title;
Views::ViewCharacters _viewCharacters;
diff --git a/engines/mm/mm1/views/protect.cpp b/engines/mm/mm1/views/protect.cpp
new file mode 100644
index 00000000000..a996b37f9c2
--- /dev/null
+++ b/engines/mm/mm1/views/protect.cpp
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/protect.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void Protect::draw() {
+ clearScreen();
+ writeString(STRING["dialogs.protect.title"]);
+ escToGoBack();
+
+
+}
+
+void Protect::printProtectionFrom() {
+ if (_textPos.y == 2)
+ writeString(STRING["dialogs.protect.protection"]);
+}
+
+void Protect::printProtectionLevel(uint protectIndex) {
+ _textPos.x = 24;
+ writeChar('+');
+ _textPos.x++;
+ writeNumber(g_globals->_activeSpells[protectIndex]);
+}
+
+bool Protect::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ return true;
+ }
+
+ return false;
+}
+
+bool Protect::msgAction(const ActionMessage &msg) {
+ if (msg._action == KEYBIND_PROTECT) {
+ addView();
+ return true;
+ }
+
+ return false;
+}
+
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/protect.h b/engines/mm/mm1/views/protect.h
new file mode 100644
index 00000000000..5eac588de5d
--- /dev/null
+++ b/engines/mm/mm1/views/protect.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_PROTECT_H
+#define MM1_VIEWS_PROTECT_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Protect : public TextView {
+private:
+ void printProtectionFrom();
+ void printProtectionLevel(uint protectIndex);
+public:
+ Protect() : TextView("Protect") {}
+ virtual ~Protect() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 5c2f9ba3ca7..85e3d9077d6 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -21,6 +21,7 @@ MODULE_OBJS := \
mm1/views/game_party.o \
mm1/views/inn.o \
mm1/views/main_menu.o \
+ mm1/views/protect.o \
mm1/views/quick_ref.o \
mm1/views/title.o \
mm1/views/text_view.o \
Commit: 76a24b344edb534484e22611d849c0ce3b9b55fb
https://github.com/scummvm/scummvm/commit/76a24b344edb534484e22611d849c0ce3b9b55fb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Finished Protect dialog
Changed paths:
A engines/mm/mm1/data/game_state.cpp
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/game_state.h
engines/mm/mm1/views/protect.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index d64e37b937f..5f64d4ecea9 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -40,7 +40,8 @@ dialogs:
protect:
title: "PROTECT: SPELLS CURRENTLY ACTIVE"
protection: "PROTECTION FROM"
- 1: 'FEAR"
+ to_attacks: "TO ATTACKS"
+ 1: "FEAR"
2: "COLD"
3: "FIRE"
4: "POISON"
diff --git a/engines/mm/mm1/data/game_state.cpp b/engines/mm/mm1/data/game_state.cpp
new file mode 100644
index 00000000000..af57cc50b0d
--- /dev/null
+++ b/engines/mm/mm1/data/game_state.cpp
@@ -0,0 +1,33 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/algorithm.h"
+#include "mm/mm1/data/game_state.h"
+
+namespace MM {
+namespace MM1 {
+
+GameState::GameState() {
+ Common::fill(&_activeSpells[0], &_activeSpells[ACTIVE_SPELLS_COUNT], 0);
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index d902dad301c..97c4585e8c6 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -23,21 +23,26 @@
#define MM1_DATA_GAME_STATE_H
#include "common/array.h"
+#include "common/rect.h"
#include "common/serializer.h"
#include "mm/mm1/data/char.h"
namespace MM {
namespace MM1 {
+#define ACTIVE_SPELLS_COUNT 18
+
/**
* This acts as a container for everything in the game
* that is persisted to savegames
*/
struct GameState {
Common::Array<Character> _party;
- Common::Array<uint> _activeSpells;
+ uint _activeSpells[ACTIVE_SPELLS_COUNT];
Common::Point _mapPos;
int _direction = 0;
+
+ GameState();
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/protect.cpp b/engines/mm/mm1/views/protect.cpp
index a996b37f9c2..743fe4373c3 100644
--- a/engines/mm/mm1/views/protect.cpp
+++ b/engines/mm/mm1/views/protect.cpp
@@ -31,12 +31,52 @@ void Protect::draw() {
writeString(STRING["dialogs.protect.title"]);
escToGoBack();
+ // Protection spells
+ _textPos.x = 0;
+ _textPos.y = 2;
+ for (int i = 0; i < 7; ++i) {
+ if (g_globals->_activeSpells[i]) {
+ printProtectionFrom();
+ writeString(STRING[Common::String::format(
+ "dialogs.protect.%d", i + 1)]);
+ printProtectionLevel(i);
+ }
+ }
+
+ // Light spell
+ if (g_globals->_activeSpells[7]) {
+ writeString(STRING["dialogs.protect.8"]);
+ writeNumber(g_globals->_activeSpells[7]);
+ writeChar(')');
+ newLine();
+ }
+ // The rest
+ for (int i = 8; i < 18; ++i) {
+ if (i == 13)
+ newLine();
+
+ if (g_globals->_activeSpells[i]) {
+ writeString(STRING[Common::String::format(
+ "dialogs.protect.%d", i + 1)]);
+ newLine();
+ }
+ }
+
+ --_textPos.y;
+ _textPos.x = 13;
+
+ if (g_globals->_activeSpells[17]) {
+ writeNumber(g_globals->_activeSpells[17]);
+ _textPos.x++;
+ writeString(STRING["dialogs.protect.to_attacks"]);
+ }
}
void Protect::printProtectionFrom() {
if (_textPos.y == 2)
writeString(STRING["dialogs.protect.protection"]);
+ _textPos.x = 17;
}
void Protect::printProtectionLevel(uint protectIndex) {
@@ -44,6 +84,8 @@ void Protect::printProtectionLevel(uint protectIndex) {
writeChar('+');
_textPos.x++;
writeNumber(g_globals->_activeSpells[protectIndex]);
+ writeChar('%');
+ newLine();
}
bool Protect::msgKeypress(const KeypressMessage &msg) {
@@ -64,7 +106,6 @@ bool Protect::msgAction(const ActionMessage &msg) {
return false;
}
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 85e3d9077d6..a05b62f6605 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
mm1/meta_engine.o \
mm1/mm1.o \
mm1/data/char.o \
+ mm1/data/game_state.o \
mm1/data/roster.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
Commit: 31395720a60365529951a93586131b8904cb719d
https://github.com/scummvm/scummvm/commit/31395720a60365529951a93586131b8904cb719d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Beginnings of map classes
Each map has an overlay file containing map specific globals
and code. So the code will need to be individually reimplemented
Changed paths:
A engines/mm/mm1/maps/map.cpp
A engines/mm/mm1/maps/map.h
A engines/mm/mm1/maps/map0.cpp
A engines/mm/mm1/maps/map0.h
A engines/mm/mm1/maps/maps.cpp
A engines/mm/mm1/maps/maps.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/globals.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 5f64d4ecea9..151a8b47061 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -93,6 +93,10 @@ dialogs:
14: "U UNLOCK"
15: "Q QUIKREF"
16: "# VIEW CH"
+ rest:
+ too_dangerous: "*** TOO DANGEROUS TO REST HERE!"
+ rest_here: "REST HERE (Y/N)?"
+ rest_complete: "REST COMPLETE: NO ENCOUNTERS!"
misc:
go_back: "'ESC' TO GO BACK"
no_characters: "NO AVAILABLE CHARACTERS"
@@ -413,3 +417,59 @@ stats:
253: "KEY CARD"
254: "EYE OF GORDOS"
255: "(USELESS ITEM)"
+maps:
+ 0: "sorpigal"
+ 1: "portsmit"
+ 2: "algary"
+ 3: "dusk"
+ 4: "erliquin"
+ 5: "cave1"
+ 6: "cave2"
+ 7: "cave3"
+ 8: "cave4"
+ 9: "cave5"
+ 10: "cave6"
+ 11: "cave7"
+ 12: "cave8"
+ 13: "cave9"
+ 14: "areaa1"
+ 15: "areaa2"
+ 16: "areaa3"
+ 17: "areaa4"
+ 18: "areab1"
+ 19: "areab2"
+ 20: "areab3"
+ 21: "areab4"
+ 22: "areac1"
+ 23: "areac2"
+ 24: "areac3"
+ 25: "areac4"
+ 26: "aread1"
+ 27: "aread2"
+ 28: "aread3"
+ 29: "aread4"
+ 30: "areae1"
+ 31: "areae2"
+ 32: "areae3"
+ 33: "areae4"
+ 34: "doom"
+ 35: "blackrn"
+ 36: "blackrs"
+ 37: "qvl1"
+ 38: "qvl2"
+ 39: "rwl1"
+ 40: "rwl2"
+ 41: "enf1"
+ 42: "enf2"
+ 43: "whitew"
+ 44: "dragad"
+ 45: "udrag1"
+ 46: "udrag2"
+ 47: "udrag3"
+ 48: "demon"
+ 49: "alamar"
+ 50: "pp1"
+ 51: "pp2"
+ 52: "pp3"
+ 53: "pp4"
+ 54: "astral"
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index d0911a1ba88..f06def68e9a 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -27,6 +27,7 @@
#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/int_array.h"
#include "mm/mm1/data/roster.h"
+#include "mm/mm1/maps/maps.h"
namespace MM {
namespace MM1 {
@@ -39,6 +40,7 @@ public:
Character *_currCharacter = nullptr;
int _startingTown = 0;
IntArray _partyChars;
+ Maps::Maps _maps;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
new file mode 100644
index 00000000000..868eb39da20
--- /dev/null
+++ b/engines/mm/mm1/maps/map.cpp
@@ -0,0 +1,35 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/maps.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+Map::Map(Maps *owner, const Common::String &name) : _name(name) {
+ owner->_maps.push_back(this);
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
new file mode 100644
index 00000000000..f1f702eb098
--- /dev/null
+++ b/engines/mm/mm1/maps/map.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP_H
+#define MM1_MAPS_MAP_H
+
+#include "common/str.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Maps;
+
+class Map {
+private:
+ Common::String _name;
+public:
+ Map(Maps *owner, const Common::String &name);
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map0.cpp b/engines/mm/mm1/maps/map0.cpp
new file mode 100644
index 00000000000..23520a0b840
--- /dev/null
+++ b/engines/mm/mm1/maps/map0.cpp
@@ -0,0 +1,32 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/utils/strings.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map0.h b/engines/mm/mm1/maps/map0.h
new file mode 100644
index 00000000000..e04fa4e17d5
--- /dev/null
+++ b/engines/mm/mm1/maps/map0.h
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP0_H
+#define MM1_MAPS_MAP0_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map0 : public Map {
+public:
+ Map0(Maps *owner) : Map(owner, "sorpigal") {}
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
new file mode 100644
index 00000000000..f7fd314b05e
--- /dev/null
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -0,0 +1,35 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/maps.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+Maps::Maps() :
+ _map0(this) {
+}
+
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
new file mode 100644
index 00000000000..857617ed2fe
--- /dev/null
+++ b/engines/mm/mm1/maps/maps.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAPS_H
+#define MM1_MAPS_MAPS_H
+
+#include "common/array.h"
+#include "mm/mm1/maps/map0.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+/**
+ * Container for all the game maps
+ */
+class Maps {
+ friend class Map;
+private:
+ Common::Array<Map *> _maps;
+ Map0 _map0;
+public:
+ Maps();
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index a05b62f6605..56f1d7f726e 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -27,6 +27,9 @@ MODULE_OBJS := \
mm1/views/title.o \
mm1/views/text_view.o \
mm1/views/view_characters.o \
+ mm1/maps/maps.o \
+ mm1/maps/map.o \
+ mm1/maps/map0.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
xeen/worldofxeen/worldofxeen_cutscenes.o \
Commit: a88fc1a918e87310d81191b9375eabff630bff98
https://github.com/scummvm/scummvm/commit/a88fc1a918e87310d81191b9375eabff630bff98
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:45+01:00
Commit Message:
MM: MM1: Adding map overlay loading
Changed paths:
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map0.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 868eb39da20..57b1e6c6369 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/file.h"
#include "mm/mm1/maps/map.h"
#include "mm/mm1/maps/maps.h"
@@ -27,7 +28,43 @@ namespace MM1 {
namespace Maps {
Map::Map(Maps *owner, const Common::String &name) : _name(name) {
- owner->_maps.push_back(this);
+ _mapId = owner->addMap(this);
+ Common::fill(&_mapData[0], &_mapData[512], 0);
+}
+
+void Map::load() {
+ loadMazeData();
+ loadOverlay();
+}
+
+void Map::loadMazeData() {
+ Common::File f;
+ if (!f.open("mazedata.dta"))
+ error("Could not open mazedata.dta");
+
+ f.seek(512 * _mapId);
+ f.read(_mapData, 512);
+ f.close();
+}
+
+void Map::loadOverlay() {
+ Common::File f;
+ if (!f.open(Common::String::format("%s.ovr", _name.c_str())))
+ error("Could not open %s.ovr overlay", _name.c_str());
+ if (f.readUint16LE() != 0xF2)
+ error("Invalid overlay header");
+
+ int globalsOffset = f.readUint16LE();
+ int globalsSize = f.readUint16LE();
+ if (globalsOffset != 0xF48F)
+ error("Invalid globals offset");
+ _globals.resize(globalsSize);
+ f.read(&_globals[0], globalsSize);
+
+ int codeOffset = f.readUint16LE();
+ int codeSize = f.readUint16LE();
+ if (codeOffset != 0xc940)
+ error("Invalid code offset");
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index f1f702eb098..1d87d2cca1c 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -22,6 +22,7 @@
#ifndef MM1_MAPS_MAP_H
#define MM1_MAPS_MAP_H
+#include "common/array.h"
#include "common/str.h"
namespace MM {
@@ -33,8 +34,26 @@ class Maps;
class Map {
private:
Common::String _name;
+ uint _mapId;
+ byte _mapData[512];
+ Common::Array<byte> _globals;
+private:
+ /**
+ * Loads the map's maze data
+ */
+ void loadMazeData();
+
+ /**
+ * Load the map's overlay file
+ */
+ void loadOverlay();
public:
Map(Maps *owner, const Common::String &name);
+
+ /**
+ * Loads the map
+ */
+ virtual void load();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map0.cpp b/engines/mm/mm1/maps/map0.cpp
index 23520a0b840..cd9db480a06 100644
--- a/engines/mm/mm1/maps/map0.cpp
+++ b/engines/mm/mm1/maps/map0.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/utils/strings.h"
+#include "mm/mm1/maps/map0.h"
namespace MM {
namespace MM1 {
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index f7fd314b05e..607b9c16d92 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -29,6 +29,11 @@ Maps::Maps() :
_map0(this) {
}
+void Maps::load(uint mapId) {
+ _mapId = mapId;
+ _currentMap = _maps[mapId];
+ _currentMap->load();
+}
} // namespace Maps
} // namespace MM1
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 857617ed2fe..82309353510 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -36,9 +36,25 @@ class Maps {
friend class Map;
private:
Common::Array<Map *> _maps;
+ uint _mapId = (uint)-1;
+ Map *_currentMap = nullptr;
+private:
Map0 _map0;
+private:
+ /**
+ * Adds map class
+ */
+ uint addMap(Map *map) {
+ _maps.push_back(map);
+ return _maps.size() - 1;
+ }
public:
Maps();
+
+ /**
+ * Load a map
+ */
+ void load(uint mapId);
};
} // namespace Maps
Commit: def2d0ef29bf0d08ef0e296fd37f17f5129e3144
https://github.com/scummvm/scummvm/commit/def2d0ef29bf0d08ef0e296fd37f17f5129e3144
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: Add console with a dump_map command
Changed paths:
A engines/mm/mm1/console.cpp
A engines/mm/mm1/console.h
A engines/mm/mm1/maps/map00.cpp
A engines/mm/mm1/maps/map00.h
R engines/mm/mm1/maps/map0.cpp
R engines/mm/mm1/maps/map0.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/mm1.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
new file mode 100644
index 00000000000..06c2410c2e0
--- /dev/null
+++ b/engines/mm/mm1/console.cpp
@@ -0,0 +1,126 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "mm/mm1/console.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+
+static int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+Console::Console() : GUI::Debugger() {
+ registerCmd("dump_map", WRAP_METHOD(Console, Cmd_DumpMap));
+}
+
+bool Console::Cmd_DumpMap(int argc, const char **argv) {
+ Common::File f;
+ Common::OutSaveFile *dest;
+
+ if (argc != 2) {
+ debugPrintf("%s <roomNum>\n", argv[0]);
+ } else {
+ int mapId = strToInt(argv[1]);
+ Maps::Map *map = g_globals->_maps.getMap(mapId);
+
+ // Dump the map data
+ if (f.open("mazedata.dta")) {
+ dest = g_system->getSavefileManager()->openForSaving(
+ Common::String::format("map%.2d-maze.bin", mapId), false);
+ assert(dest);
+ byte buffer[512];
+
+ f.seek(mapId * 512);
+ f.read(buffer, 512);
+ dest->write(buffer, 512);
+
+ dest->finalize();
+ delete dest;
+ f.close();
+ }
+
+ if (f.open(Common::String::format("%s.ovr", map->getName().c_str()))) {
+ int magicId = f.readUint16LE();
+ int codePtr = f.readUint16LE();
+ int codeSize = f.readUint16LE();
+ int dataPtr = f.readUint16LE();
+ int dataSize = f.readUint16LE();
+ int extrasSize = f.readUint16LE();
+ int startPtr = f.readUint16LE();
+
+ assert(magicId == 0xf2);
+ assert(startPtr >= codePtr &&
+ startPtr < (codePtr + codeSize));
+
+ dest = g_system->getSavefileManager()->openForSaving(
+ Common::String::format("map%.2d-code.bin", mapId), false);
+ byte *code = new byte[codeSize];
+ f.read(code, codeSize);
+
+ for (int i = 0; i < (codePtr % 16); ++i)
+ dest->writeByte(0);
+ dest->write(code, codeSize);
+ dest->flush();
+ delete dest;
+ delete[] code;
+
+ dest = g_system->getSavefileManager()->openForSaving(
+ Common::String::format("map%.2d-data.bin", mapId), false);
+ byte *data = new byte[dataSize];
+ f.read(data, dataSize);
+ dest->write(data, dataSize);
+ dest->flush();
+ delete dest;
+ delete[] data;
+
+ f.close();
+
+ debugPrintf("data: ptr=%xh, size=%xh\n", dataPtr, dataSize);
+ debugPrintf("code: ptr=%xh, size=%xh start=%xh\n",
+ codePtr, codeSize, startPtr);
+ debugPrintf("Extras size=%xh\n", extrasSize);
+ }
+
+ debugPrintf("Done.\n");
+ }
+
+ return true;
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
new file mode 100644
index 00000000000..73720f4c265
--- /dev/null
+++ b/engines/mm/mm1/console.h
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_MM1_CONSOLE_H
+#define MM_MM1_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace MM {
+namespace MM1 {
+
+class Console : public GUI::Debugger {
+protected:
+ bool Cmd_DumpMap(int argc, const char **argv);
+
+public:
+ Console();
+ ~Console() override {}
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 1d87d2cca1c..b545e650f47 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -50,6 +50,11 @@ private:
public:
Map(Maps *owner, const Common::String &name);
+ /**
+ * Gets the map name
+ */
+ Common::String getName() const { return _name; }
+
/**
* Loads the map
*/
diff --git a/engines/mm/mm1/maps/map0.cpp b/engines/mm/mm1/maps/map00.cpp
similarity index 96%
rename from engines/mm/mm1/maps/map0.cpp
rename to engines/mm/mm1/maps/map00.cpp
index cd9db480a06..963a69a0ff0 100644
--- a/engines/mm/mm1/maps/map0.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/maps/map0.h"
+#include "mm/mm1/maps/map00.h"
namespace MM {
namespace MM1 {
diff --git a/engines/mm/mm1/maps/map0.h b/engines/mm/mm1/maps/map00.h
similarity index 93%
rename from engines/mm/mm1/maps/map0.h
rename to engines/mm/mm1/maps/map00.h
index e04fa4e17d5..d6333475673 100644
--- a/engines/mm/mm1/maps/map0.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -28,9 +28,9 @@ namespace MM {
namespace MM1 {
namespace Maps {
-class Map0 : public Map {
+class Map00 : public Map {
public:
- Map0(Maps *owner) : Map(owner, "sorpigal") {}
+ Map00(Maps *owner) : Map(owner, "sorpigal") {}
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 607b9c16d92..60921c5aa92 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -26,7 +26,7 @@ namespace MM1 {
namespace Maps {
Maps::Maps() :
- _map0(this) {
+ _map00(this) {
}
void Maps::load(uint mapId) {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 82309353510..a62ac001a78 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -23,7 +23,7 @@
#define MM1_MAPS_MAPS_H
#include "common/array.h"
-#include "mm/mm1/maps/map0.h"
+#include "mm/mm1/maps/map00.h"
namespace MM {
namespace MM1 {
@@ -39,7 +39,7 @@ private:
uint _mapId = (uint)-1;
Map *_currentMap = nullptr;
private:
- Map0 _map0;
+ Map00 _map00;
private:
/**
* Adds map class
@@ -55,6 +55,11 @@ public:
* Load a map
*/
void load(uint mapId);
+
+ /**
+ * Get a given map
+ */
+ Map *getMap(uint mapId) const { return _maps[mapId]; }
};
} // namespace Maps
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 380df327e14..7f466a12aaa 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -25,6 +25,7 @@
#include "common/events.h"
#include "engines/util.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/console.h"
#include "mm/mm1/gfx/gfx.h"
namespace MM {
@@ -46,6 +47,8 @@ Common::Error MM1Engine::run() {
initGraphics(320, 200);
Gfx::GFX::setEgaPalette(0);
+ setDebugger(new Console());
+
// Load globals
if (!_globals.load())
return Common::kNoError;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 56f1d7f726e..7fbbc33abdb 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS := \
meta_engine.o \
utils/engine_data.o \
utils/strings_data.o \
+ mm1/console.o \
mm1/events.o \
mm1/globals.o \
mm1/meta_engine.o \
@@ -29,7 +30,7 @@ MODULE_OBJS := \
mm1/views/view_characters.o \
mm1/maps/maps.o \
mm1/maps/map.o \
- mm1/maps/map0.o \
+ mm1/maps/map00.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
xeen/worldofxeen/worldofxeen_cutscenes.o \
Commit: cae78f2db83cb8bf62173812213715a8b6a43da5
https://github.com/scummvm/scummvm/commit/cae78f2db83cb8bf62173812213715a8b6a43da5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: Added map_string debugger command
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 06c2410c2e0..592b4baf249 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -46,6 +46,7 @@ static int strToInt(const char *s) {
Console::Console() : GUI::Debugger() {
registerCmd("dump_map", WRAP_METHOD(Console, Cmd_DumpMap));
+ registerCmd("map_string", WRAP_METHOD(Console, Cmd_MapString));
}
bool Console::Cmd_DumpMap(int argc, const char **argv) {
@@ -122,5 +123,43 @@ bool Console::Cmd_DumpMap(int argc, const char **argv) {
return true;
}
+bool Console::Cmd_MapString(int argc, const char **argv) {
+ Common::File f;
+
+ if (argc != 3) {
+ debugPrintf("%s <map Id> <offset>\n");
+ } else {
+ int mapId = strToInt(argv[1]);
+ Maps::Map *map = g_globals->_maps.getMap(mapId);
+ int offset = strToInt(Common::String::format(
+ "%sh", argv[2]).c_str());
+
+ if (!f.open(Common::String::format("%s.ovr", map->getName().c_str())))
+ error("Failed to open map");
+
+ f.readUint16LE();
+ f.readUint16LE();
+ int codeSize = f.readUint16LE();
+ int dataPtr = f.readUint16LE();
+ f.readUint16LE();
+ f.readUint16LE();
+ f.readUint16LE();
+
+ f.skip(codeSize);
+ f.skip(offset - dataPtr);
+
+ // Read the string
+ Common::String s;
+ char c;
+ while ((c = f.readByte()) != '\0')
+ s += c;
+ f.close();
+
+ debugPrintf("\"%s\"\n", s.c_str());
+ }
+
+ return true;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index 73720f4c265..07bccdcde5b 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -29,8 +29,16 @@ namespace MM1 {
class Console : public GUI::Debugger {
protected:
+ /**
+ * Used to dump a map's code and data
+ */
bool Cmd_DumpMap(int argc, const char **argv);
+ /**
+ * Prints a string from within a map's data segment
+ */
+ bool Cmd_MapString(int argc, const char **argv);
+
public:
Console();
~Console() override {}
Commit: b6a3465b806d6d2b80ee4002388240fe962fd860
https://github.com/scummvm/scummvm/commit/b6a3465b806d6d2b80ee4002388240fe962fd860
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: Added placeholder map classes
Changed paths:
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 60921c5aa92..e812cd0645d 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -26,7 +26,20 @@ namespace MM1 {
namespace Maps {
Maps::Maps() :
- _map00(this) {
+ _map00(this), _map01(this), _map02(this), _map03(this),
+ _map04(this), _map05(this), _map06(this), _map07(this),
+ _map08(this), _map09(this), _map10(this), _map11(this),
+ _map12(this), _map13(this), _map14(this), _map15(this),
+ _map16(this), _map17(this), _map18(this), _map19(this),
+ _map20(this), _map21(this), _map22(this), _map23(this),
+ _map24(this), _map25(this), _map26(this), _map27(this),
+ _map28(this), _map29(this), _map30(this), _map31(this),
+ _map32(this), _map33(this), _map34(this), _map35(this),
+ _map36(this), _map37(this), _map38(this), _map39(this),
+ _map40(this), _map41(this), _map42(this), _map43(this),
+ _map44(this), _map45(this), _map46(this), _map47(this),
+ _map48(this), _map49(this), _map50(this), _map51(this),
+ _map52(this), _map53(this), _map54(this) {
}
void Maps::load(uint mapId) {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index a62ac001a78..ec66f58303b 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -29,6 +29,69 @@ namespace MM {
namespace MM1 {
namespace Maps {
+/** PLACEHOLDER MAPS **/
+#define PLACEHOLDER(ID, NAME) \
+ class Map##ID : public Map { \
+ public: \
+ Map##ID(Maps *owner) : Map(owner, NAME) {} \
+ }
+
+PLACEHOLDER(01, "portsmit");
+PLACEHOLDER(02, "algary");
+PLACEHOLDER(03, "dusk");
+PLACEHOLDER(04, "erliquin");
+PLACEHOLDER(05, "cave1");
+PLACEHOLDER(06, "cave2");
+PLACEHOLDER(07, "cave3");
+PLACEHOLDER(08, "cave4");
+PLACEHOLDER(09, "cave5");
+PLACEHOLDER(10, "cave6");
+PLACEHOLDER(11, "cave7");
+PLACEHOLDER(12, "cave8");
+PLACEHOLDER(13, "cave9");
+PLACEHOLDER(14, "areaa1");
+PLACEHOLDER(15, "areaa2");
+PLACEHOLDER(16, "areaa3");
+PLACEHOLDER(17, "areaa4");
+PLACEHOLDER(18, "areab1");
+PLACEHOLDER(19, "areab2");
+PLACEHOLDER(20, "areab3");
+PLACEHOLDER(21, "areab4");
+PLACEHOLDER(22, "areac1");
+PLACEHOLDER(23, "areac2");
+PLACEHOLDER(24, "areac3");
+PLACEHOLDER(25, "areac4");
+PLACEHOLDER(26, "aread1");
+PLACEHOLDER(27, "aread2");
+PLACEHOLDER(28, "aread3");
+PLACEHOLDER(29, "aread4");
+PLACEHOLDER(30, "areae1");
+PLACEHOLDER(31, "areae2");
+PLACEHOLDER(32, "areae3");
+PLACEHOLDER(33, "areae4");
+PLACEHOLDER(34, "doom");
+PLACEHOLDER(35, "blackrn");
+PLACEHOLDER(36, "blackrs");
+PLACEHOLDER(37, "qvl1");
+PLACEHOLDER(38, "qvl2");
+PLACEHOLDER(39, "rwl1");
+PLACEHOLDER(40, "rwl2");
+PLACEHOLDER(41, "enf1");
+PLACEHOLDER(42, "enf2");
+PLACEHOLDER(43, "whitew");
+PLACEHOLDER(44, "dragad");
+PLACEHOLDER(45, "udrag1");
+PLACEHOLDER(46, "udrag2");
+PLACEHOLDER(47, "udrag3");
+PLACEHOLDER(48, "demon");
+PLACEHOLDER(49, "alamar");
+PLACEHOLDER(50, "pp1");
+PLACEHOLDER(51, "pp2");
+PLACEHOLDER(52, "pp3");
+PLACEHOLDER(53, "pp4");
+PLACEHOLDER(54, "astral");
+#undef PLACEHOLDER
+
/**
* Container for all the game maps
*/
@@ -40,6 +103,60 @@ private:
Map *_currentMap = nullptr;
private:
Map00 _map00;
+ Map01 _map01;
+ Map02 _map02;
+ Map03 _map03;
+ Map04 _map04;
+ Map05 _map05;
+ Map06 _map06;
+ Map07 _map07;
+ Map08 _map08;
+ Map09 _map09;
+ Map10 _map10;
+ Map11 _map11;
+ Map12 _map12;
+ Map13 _map13;
+ Map14 _map14;
+ Map15 _map15;
+ Map16 _map16;
+ Map17 _map17;
+ Map18 _map18;
+ Map19 _map19;
+ Map20 _map20;
+ Map21 _map21;
+ Map22 _map22;
+ Map23 _map23;
+ Map24 _map24;
+ Map25 _map25;
+ Map26 _map26;
+ Map27 _map27;
+ Map28 _map28;
+ Map29 _map29;
+ Map30 _map30;
+ Map31 _map31;
+ Map32 _map32;
+ Map33 _map33;
+ Map34 _map34;
+ Map35 _map35;
+ Map36 _map36;
+ Map37 _map37;
+ Map38 _map38;
+ Map39 _map39;
+ Map40 _map40;
+ Map41 _map41;
+ Map42 _map42;
+ Map43 _map43;
+ Map44 _map44;
+ Map45 _map45;
+ Map46 _map46;
+ Map47 _map47;
+ Map48 _map48;
+ Map49 _map49;
+ Map50 _map50;
+ Map51 _map51;
+ Map52 _map52;
+ Map53 _map53;
+ Map54 _map54;
private:
/**
* Adds map class
Commit: 2f7672f7dbe1f1214f1b9aa9ba78051fabb9b36f
https://github.com/scummvm/scummvm/commit/2f7672f7dbe1f1214f1b9aa9ba78051fabb9b36f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: Add the strings from map 0 to strings yml
Adding map strings to the yml file will make it
easier to create fan translations in the long term
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/console.cpp
engines/mm/utils/strings_data.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 151a8b47061..08da486deaf 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -418,58 +418,20 @@ stats:
254: "EYE OF GORDOS"
255: "(USELESS ITEM)"
maps:
- 0: "sorpigal"
- 1: "portsmit"
- 2: "algary"
- 3: "dusk"
- 4: "erliquin"
- 5: "cave1"
- 6: "cave2"
- 7: "cave3"
- 8: "cave4"
- 9: "cave5"
- 10: "cave6"
- 11: "cave7"
- 12: "cave8"
- 13: "cave9"
- 14: "areaa1"
- 15: "areaa2"
- 16: "areaa3"
- 17: "areaa4"
- 18: "areab1"
- 19: "areab2"
- 20: "areab3"
- 21: "areab4"
- 22: "areac1"
- 23: "areac2"
- 24: "areac3"
- 25: "areac4"
- 26: "aread1"
- 27: "aread2"
- 28: "aread3"
- 29: "aread4"
- 30: "areae1"
- 31: "areae2"
- 32: "areae3"
- 33: "areae4"
- 34: "doom"
- 35: "blackrn"
- 36: "blackrs"
- 37: "qvl1"
- 38: "qvl2"
- 39: "rwl1"
- 40: "rwl2"
- 41: "enf1"
- 42: "enf2"
- 43: "whitew"
- 44: "dragad"
- 45: "udrag1"
- 46: "udrag2"
- 47: "udrag3"
- 48: "demon"
- 49: "alamar"
- 50: "pp1"
- 51: "pp2"
- 52: "pp3"
- 53: "pp4"
- 54: "astral"
+ map00:
+ c9d3: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
+ ca28: """EULARDS FINE FOODS"""
+ ca3d: """B AND B BLACKSMITHING"""
+ ca53: """THE INN OF SORPIGAL"""
+ ca0a: "A SIGN ABOVE THE DOOR READS: "
+ ca69: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
+ cade: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
+ cdcb: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ cb56: "STEP UP TO THE BAR (Y/N)?"
+ cb70: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
+ cbc8: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
+ cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
+ cd2e: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
+ cd53: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
+ cdf3: "TRAP DOOR!"
+ cdfe: ", LEVITATION SAVES YOU!"
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 592b4baf249..46b53a2de03 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -151,11 +151,24 @@ bool Console::Cmd_MapString(int argc, const char **argv) {
// Read the string
Common::String s;
char c;
- while ((c = f.readByte()) != '\0')
- s += c;
- f.close();
+
+ while ((c = f.readByte()) != '\0') {
+ if (c == '\r') {
+ s += "\\n";
+ debugPrintf("%s\n", s.c_str());
+ s = "";
+ } else {
+ s += c;
+
+ if (s.size() == 40) {
+ debugPrintf("%s\n", s.c_str());
+ s = "";
+ }
+ }
+ }
+ debugPrintf("%s\n", s.c_str());
- debugPrintf("\"%s\"\n", s.c_str());
+ f.close();
}
return true;
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
index 63613a1b7d7..bf40f4fd602 100644
--- a/engines/mm/utils/strings_data.cpp
+++ b/engines/mm/utils/strings_data.cpp
@@ -38,7 +38,7 @@ bool StringsData::load(const Common::String &filename) {
// Get the next line
Common::String line = f.readLine();
- // Check for blank or commen tlines
+ // Check for blank or comment lines
Common::String lineTrimmed = line;
lineTrimmed.trim();
if (lineTrimmed.empty() || lineTrimmed.hasPrefix("#"))
@@ -61,12 +61,22 @@ bool StringsData::load(const Common::String &filename) {
key.trim();
value.trim();
- // Handle quoted string values
+ // Strip quotes from start and end of string
if (value.hasPrefix("\"") && value.hasSuffix("\"")) {
value.deleteChar(0);
value.deleteLastChar();
}
+ // Replace any sequences
+ for (uint i = 0; i < value.size(); ++i) {
+ if (value[i] == '\\' && value[i + 1] == '\n') {
+ value.deleteChar(i);
+ value.setChar(i, '\n');
+ } else if (value[i] == '"' && value[i + 1] == '"') {
+ value.deleteChar(i);
+ }
+ }
+
// Handle the entries
if (numTabs == prefixKeys.size()) {
// Do nothing
Commit: d584fd7a7ac86e749c8bbd25c7b21b99bd7c85ec
https://github.com/scummvm/scummvm/commit/d584fd7a7ac86e749c8bbd25c7b21b99bd7c85ec
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: Figured out wall types part of map data
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 08da486deaf..980524548a0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -433,5 +433,9 @@ maps:
cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
cd2e: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
cd53: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
+ cd7c: "YE OLDE HOGGE TAVERN"
+ cd93: "TEMPLE MOONSHADOW"
+ cda7: "OTTO'S TRAINING"
+ cdb9: "JAIL. KEEP OUT!"
cdf3: "TRAP DOOR!"
cdfe: ", LEVITATION SAVES YOU!"
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 57b1e6c6369..df31e934996 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -29,7 +29,8 @@ namespace Maps {
Map::Map(Maps *owner, const Common::String &name) : _name(name) {
_mapId = owner->addMap(this);
- Common::fill(&_mapData[0], &_mapData[512], 0);
+ Common::fill((byte *)&_walls[0], (byte *)&_walls[MAP_SIZE], 0);
+ Common::fill(&_states[0], (byte *)&_states[MAP_SIZE], 0);
}
void Map::load() {
@@ -43,7 +44,8 @@ void Map::loadMazeData() {
error("Could not open mazedata.dta");
f.seek(512 * _mapId);
- f.read(_mapData, 512);
+ f.read((byte *)_walls, MAP_SIZE);
+ f.read(_states, MAP_SIZE);
f.close();
}
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index b545e650f47..c8642a65473 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -29,13 +29,34 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define MAP_W 16
+#define MAP_H 16
+#define MAP_SIZE (MAP_W * MAP_H)
+
class Maps;
+enum WallType {
+ WALL_NONE = 0, WALL_NORMAL = 1, WALL_DOOR = 2,
+ WALL_TORCH = 3
+};
+
+/**
+ * The byte structure representing the wall types
+ * for the four cardinal directions
+ */
+struct MapWalls {
+ WallType _n : 2;
+ WallType _e : 2;
+ WallType _s : 2;
+ WallType _w : 2;
+};
+
class Map {
private:
Common::String _name;
uint _mapId;
- byte _mapData[512];
+ MapWalls _walls[MAP_SIZE];
+ byte _states[MAP_SIZE];
Common::Array<byte> _globals;
private:
/**
Commit: 58d23965658d81853baf1d0410ea46ffbe550e80
https://github.com/scummvm/scummvm/commit/58d23965658d81853baf1d0410ea46ffbe550e80
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: More map data loading
Changed paths:
engines/mm/mm1/data/game_state.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index 97c4585e8c6..67182f09795 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -39,8 +39,6 @@ namespace MM1 {
struct GameState {
Common::Array<Character> _party;
uint _activeSpells[ACTIVE_SPELLS_COUNT];
- Common::Point _mapPos;
- int _direction = 0;
GameState();
};
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index df31e934996..297d33047e9 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -27,7 +27,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
-Map::Map(Maps *owner, const Common::String &name) : _name(name) {
+Map::Map(Maps *owner, const Common::String &name, uint16 id) :
+ _name(name), _id(id) {
_mapId = owner->addMap(this);
Common::fill((byte *)&_walls[0], (byte *)&_walls[MAP_SIZE], 0);
Common::fill(&_states[0], (byte *)&_states[MAP_SIZE], 0);
@@ -53,20 +54,25 @@ void Map::loadOverlay() {
Common::File f;
if (!f.open(Common::String::format("%s.ovr", _name.c_str())))
error("Could not open %s.ovr overlay", _name.c_str());
- if (f.readUint16LE() != 0xF2)
- error("Invalid overlay header");
- int globalsOffset = f.readUint16LE();
- int globalsSize = f.readUint16LE();
- if (globalsOffset != 0xF48F)
- error("Invalid globals offset");
- _globals.resize(globalsSize);
- f.read(&_globals[0], globalsSize);
-
- int codeOffset = f.readUint16LE();
+ int magicId = f.readUint16LE();
+ int codePtr = f.readUint16LE();
int codeSize = f.readUint16LE();
- if (codeOffset != 0xc940)
- error("Invalid code offset");
+ f.readUint16LE(); // dataPtr
+ int dataSize = f.readUint16LE();
+ f.readUint16LE(); // extras size
+ f.readUint16LE(); // code entry-point
+
+ if (magicId != 0xF2 || codePtr != 0xF48F)
+ error("Invalid map overlay header");
+
+ // Skip over code segment, since each map's
+ // code is going to be reimplemented in C++
+ f.skip(codeSize);
+
+ // Read in the data segment
+ _data.resize(dataSize);
+ f.read(&_data[0], dataSize);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index c8642a65473..9fb765487b3 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -54,10 +54,11 @@ struct MapWalls {
class Map {
private:
Common::String _name;
+ uint16 _id;
uint _mapId;
MapWalls _walls[MAP_SIZE];
byte _states[MAP_SIZE];
- Common::Array<byte> _globals;
+ Common::Array<byte> _data;
private:
/**
* Loads the map's maze data
@@ -69,7 +70,13 @@ private:
*/
void loadOverlay();
public:
- Map(Maps *owner, const Common::String &name);
+ Map(Maps *owner, const Common::String &name, uint16 id);
+ virtual ~Map() {}
+
+ /**
+ * Loads the map
+ */
+ virtual void load();
/**
* Gets the map name
@@ -77,9 +84,19 @@ public:
Common::String getName() const { return _name; }
/**
- * Loads the map
+ * Returns the map Id
*/
- virtual void load();
+ uint16 getId() const { return _id; }
+
+ /**
+ * Accesses the map data
+ */
+ const byte &operator[](uint ofs) const {
+ return _data[ofs];
+ }
+ byte &operator[](uint ofs) {
+ return _data[ofs];
+ }
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index d6333475673..3b3171fe8c4 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -30,7 +30,7 @@ namespace Maps {
class Map00 : public Map {
public:
- Map00(Maps *owner) : Map(owner, "sorpigal") {}
+ Map00(Maps *owner) : Map(owner, "sorpigal", 0x604) {}
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index e812cd0645d..a524d950ef8 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -19,33 +19,63 @@
*
*/
+#include "common/endian.h"
#include "mm/mm1/maps/maps.h"
namespace MM {
namespace MM1 {
namespace Maps {
+static byte LOOKUPS_START[4] = { 0, 0, 14, 34 };
+static byte COLOR_OFFSET[55] = {
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
+};
+
Maps::Maps() :
- _map00(this), _map01(this), _map02(this), _map03(this),
- _map04(this), _map05(this), _map06(this), _map07(this),
- _map08(this), _map09(this), _map10(this), _map11(this),
- _map12(this), _map13(this), _map14(this), _map15(this),
- _map16(this), _map17(this), _map18(this), _map19(this),
- _map20(this), _map21(this), _map22(this), _map23(this),
- _map24(this), _map25(this), _map26(this), _map27(this),
- _map28(this), _map29(this), _map30(this), _map31(this),
- _map32(this), _map33(this), _map34(this), _map35(this),
- _map36(this), _map37(this), _map38(this), _map39(this),
- _map40(this), _map41(this), _map42(this), _map43(this),
- _map44(this), _map45(this), _map46(this), _map47(this),
- _map48(this), _map49(this), _map50(this), _map51(this),
- _map52(this), _map53(this), _map54(this) {
+ _map00(this), _map01(this), _map02(this), _map03(this),
+ _map04(this), _map05(this), _map06(this), _map07(this),
+ _map08(this), _map09(this), _map10(this), _map11(this),
+ _map12(this), _map13(this), _map14(this), _map15(this),
+ _map16(this), _map17(this), _map18(this), _map19(this),
+ _map20(this), _map21(this), _map22(this), _map23(this),
+ _map24(this), _map25(this), _map26(this), _map27(this),
+ _map28(this), _map29(this), _map30(this), _map31(this),
+ _map32(this), _map33(this), _map34(this), _map35(this),
+ _map36(this), _map37(this), _map38(this), _map39(this),
+ _map40(this), _map41(this), _map42(this), _map43(this),
+ _map44(this), _map45(this), _map46(this), _map47(this),
+ _map48(this), _map49(this), _map50(this), _map51(this),
+ _map52(this), _map53(this), _map54(this) {
+ Common::fill(&_data1[0], &_data1[32], 0);
}
void Maps::load(uint mapId) {
_mapId = mapId;
_currentMap = _maps[mapId];
_currentMap->load();
+ Common::fill(&_data1[0], &_data1[32], 0);
+}
+
+void Maps::select(byte section, byte v1, byte v2) {
+ uint mapId = getIndex(section, v1, v2);
+ load(mapId);
+}
+
+uint Maps::getIndex(byte section, byte v1, byte v2) {
+ uint16 id = MKTAG16(v2, v1);
+ uint idx = LOOKUPS_START[section / 2];
+
+ // Find map by Id
+ for (; id != _maps[idx]->getId(); ++idx) {
+ assert(idx < _maps.size());
+ }
+
+ _colorOffset = COLOR_OFFSET[idx];
+ return idx;
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index ec66f58303b..c484f56ef6d 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -23,6 +23,7 @@
#define MM1_MAPS_MAPS_H
#include "common/array.h"
+#include "common/rect.h"
#include "mm/mm1/maps/map00.h"
namespace MM {
@@ -30,66 +31,66 @@ namespace MM1 {
namespace Maps {
/** PLACEHOLDER MAPS **/
-#define PLACEHOLDER(ID, NAME) \
- class Map##ID : public Map { \
+#define PLACEHOLDER(INDEX, NAME, ID) \
+ class Map##INDEX : public Map { \
public: \
- Map##ID(Maps *owner) : Map(owner, NAME) {} \
+ Map##INDEX(Maps *owner) : Map(owner, NAME, ID) {} \
}
-PLACEHOLDER(01, "portsmit");
-PLACEHOLDER(02, "algary");
-PLACEHOLDER(03, "dusk");
-PLACEHOLDER(04, "erliquin");
-PLACEHOLDER(05, "cave1");
-PLACEHOLDER(06, "cave2");
-PLACEHOLDER(07, "cave3");
-PLACEHOLDER(08, "cave4");
-PLACEHOLDER(09, "cave5");
-PLACEHOLDER(10, "cave6");
-PLACEHOLDER(11, "cave7");
-PLACEHOLDER(12, "cave8");
-PLACEHOLDER(13, "cave9");
-PLACEHOLDER(14, "areaa1");
-PLACEHOLDER(15, "areaa2");
-PLACEHOLDER(16, "areaa3");
-PLACEHOLDER(17, "areaa4");
-PLACEHOLDER(18, "areab1");
-PLACEHOLDER(19, "areab2");
-PLACEHOLDER(20, "areab3");
-PLACEHOLDER(21, "areab4");
-PLACEHOLDER(22, "areac1");
-PLACEHOLDER(23, "areac2");
-PLACEHOLDER(24, "areac3");
-PLACEHOLDER(25, "areac4");
-PLACEHOLDER(26, "aread1");
-PLACEHOLDER(27, "aread2");
-PLACEHOLDER(28, "aread3");
-PLACEHOLDER(29, "aread4");
-PLACEHOLDER(30, "areae1");
-PLACEHOLDER(31, "areae2");
-PLACEHOLDER(32, "areae3");
-PLACEHOLDER(33, "areae4");
-PLACEHOLDER(34, "doom");
-PLACEHOLDER(35, "blackrn");
-PLACEHOLDER(36, "blackrs");
-PLACEHOLDER(37, "qvl1");
-PLACEHOLDER(38, "qvl2");
-PLACEHOLDER(39, "rwl1");
-PLACEHOLDER(40, "rwl2");
-PLACEHOLDER(41, "enf1");
-PLACEHOLDER(42, "enf2");
-PLACEHOLDER(43, "whitew");
-PLACEHOLDER(44, "dragad");
-PLACEHOLDER(45, "udrag1");
-PLACEHOLDER(46, "udrag2");
-PLACEHOLDER(47, "udrag3");
-PLACEHOLDER(48, "demon");
-PLACEHOLDER(49, "alamar");
-PLACEHOLDER(50, "pp1");
-PLACEHOLDER(51, "pp2");
-PLACEHOLDER(52, "pp3");
-PLACEHOLDER(53, "pp4");
-PLACEHOLDER(54, "astral");
+PLACEHOLDER(01, "portsmit", 0xC03);
+PLACEHOLDER(02, "algary", 0x203);
+PLACEHOLDER(03, "dusk", 0x802);
+PLACEHOLDER(04, "erliquin", 0x0B1A);
+PLACEHOLDER(05, "cave1", 0x0A11);
+PLACEHOLDER(06, "cave2", 0x1);
+PLACEHOLDER(07, "cave3", 0xC01);
+PLACEHOLDER(08, "cave4", 0x202);
+PLACEHOLDER(09, "cave5", 0x5);
+PLACEHOLDER(10, "cave6", 0x51B);
+PLACEHOLDER(11, "cave7", 0x212);
+PLACEHOLDER(12, "cave8", 0x601);
+PLACEHOLDER(13, "cave9", 0xA00);
+PLACEHOLDER(14, "areaa1", 0xF01);
+PLACEHOLDER(15, "areaa2", 0x502);
+PLACEHOLDER(16, "areaa3", 0xB02);
+PLACEHOLDER(17, "areaa4", 0x103);
+PLACEHOLDER(18, "areab1", 0xA00);
+PLACEHOLDER(19, "areab2", 0x703);
+PLACEHOLDER(20, "areab3", 0x101);
+PLACEHOLDER(21, "areab4", 0xD03);
+PLACEHOLDER(22, "areac1", 0x304);
+PLACEHOLDER(23, "areac2", 0xA11);
+PLACEHOLDER(24, "areac3", 0x904);
+PLACEHOLDER(25, "areac4", 0xF04);
+PLACEHOLDER(26, "aread1", 0x505);
+PLACEHOLDER(27, "aread2", 0xB05);
+PLACEHOLDER(28, "aread3", 0x106);
+PLACEHOLDER(29, "aread4", 0x801);
+PLACEHOLDER(30, "areae1", 0x112);
+PLACEHOLDER(31, "areae2", 0x706);
+PLACEHOLDER(32, "areae3", 0xB1A);
+PLACEHOLDER(33, "areae4", 0x11B);
+PLACEHOLDER(34, "doom", 0x706);
+PLACEHOLDER(35, "blackrn", 0xF08);
+PLACEHOLDER(36, "blackrs", 0x508);
+PLACEHOLDER(37, "qvl1", 0xF03);
+PLACEHOLDER(38, "qvl2", 0x703);
+PLACEHOLDER(39, "rwl1", 0xF02);
+PLACEHOLDER(40, "rwl2", 0x702);
+PLACEHOLDER(41, "enf1", 0xF04);
+PLACEHOLDER(42, "enf2", 0x704);
+PLACEHOLDER(43, "whitew", 0xA11);
+PLACEHOLDER(44, "dragad", 0x107);
+PLACEHOLDER(45, "udrag1", 0xF05);
+PLACEHOLDER(46, "udrag2", 0xA00);
+PLACEHOLDER(47, "udrag3", 0x705);
+PLACEHOLDER(48, "demon", 0x412);
+PLACEHOLDER(49, "alamar", 0xB07);
+PLACEHOLDER(50, "pp1", 0xF01);
+PLACEHOLDER(51, "pp2", 0x701);
+PLACEHOLDER(52, "pp3", 0xE00);
+PLACEHOLDER(53, "pp4", 0x201);
+PLACEHOLDER(54, "astral", 0xB1A);
#undef PLACEHOLDER
/**
@@ -99,8 +100,6 @@ class Maps {
friend class Map;
private:
Common::Array<Map *> _maps;
- uint _mapId = (uint)-1;
- Map *_currentMap = nullptr;
private:
Map00 _map00;
Map01 _map01;
@@ -165,6 +164,18 @@ private:
_maps.push_back(map);
return _maps.size() - 1;
}
+
+ /**
+ * Gets the index of a map given the id values
+ */
+ uint getIndex(byte section, byte v1, byte v2);
+public:
+ uint _mapId = (uint)-1;
+ Common::Point _mapPos;
+ byte _mapDirectionMask = 0;
+ Map *_currentMap = nullptr;
+ byte _data1[32];
+ int _colorOffset = 0;
public:
Maps();
@@ -173,6 +184,11 @@ public:
*/
void load(uint mapId);
+ /**
+ * Selects a map
+ */
+ void select(byte section, byte v1, byte v2);
+
/**
* Get a given map
*/
Commit: 95e8c8ab02c371288e32cd50e3ecc1b885c10a13
https://github.com/scummvm/scummvm/commit/95e8c8ab02c371288e32cd50e3ecc1b885c10a13
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: Map loading method that triggers game view
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 4808c246124..5685fb95207 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -49,6 +49,13 @@ struct KeypressMessage : public Message, public Common::KeyState {
Message(), Common::KeyState(ks) {}
};
+struct GameMessage : public Message {
+ Common::String _name;
+ GameMessage() : Message() {}
+ GameMessage(const Common::String &name) : Message(),
+ _name(name) {}
+};
+
class UIElement {
friend class Events;
protected:
@@ -138,6 +145,7 @@ public:
MESSAGE(Unfocus);
MESSAGE(Keypress);
MESSAGE(Action);
+ MESSAGE(Game);
#undef MESSAGE
};
@@ -208,6 +216,7 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
+ MESSAGE(Game);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 297d33047e9..d49e5df089d 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -75,6 +75,10 @@ void Map::loadOverlay() {
f.read(&_data[0], dataSize);
}
+void Map::getData() {
+ // TODO
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 9fb765487b3..abc5a0c1daf 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -97,6 +97,12 @@ public:
byte &operator[](uint ofs) {
return _data[ofs];
}
+
+ /**
+ * Loads some common data values from the map's
+ * data segment into fields
+ */
+ void getData();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index a524d950ef8..8ca6663704e 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -21,6 +21,7 @@
#include "common/endian.h"
#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
namespace MM {
namespace MM1 {
@@ -60,13 +61,19 @@ void Maps::load(uint mapId) {
Common::fill(&_data1[0], &_data1[32], 0);
}
-void Maps::select(byte section, byte v1, byte v2) {
- uint mapId = getIndex(section, v1, v2);
+void Maps::select(byte section, byte id1, byte id2) {
+ uint mapId = getIndex(section, id1, id2);
load(mapId);
}
-uint Maps::getIndex(byte section, byte v1, byte v2) {
- uint16 id = MKTAG16(v2, v1);
+void Maps::display(byte id1, byte id2, byte section) {
+ select(section, id1, id2);
+ _currentMap->getData();
+ g_events->msgGame(GameMessage("DISPLAY"));
+}
+
+uint Maps::getIndex(byte section, byte id1, byte id2) {
+ uint16 id = MKTAG16(id2, id1);
uint idx = LOOKUPS_START[section / 2];
// Find map by Id
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index c484f56ef6d..d12218cf5f2 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -187,7 +187,12 @@ public:
/**
* Selects a map
*/
- void select(byte section, byte v1, byte v2);
+ void select(byte section, byte id1, byte id2);
+
+ /**
+ * Selects a map, and switches to in-game display
+ */
+ void display(byte id1, byte id2, byte section = 1);
/**
* Get a given map
Commit: ac9389c2b26dfca0add1591c13716e4ff5588352
https://github.com/scummvm/scummvm/commit/ac9389c2b26dfca0add1591c13716e4ff5588352
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: The map getData method is actually for loading tiles
Changed paths:
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index d49e5df089d..297d33047e9 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -75,10 +75,6 @@ void Map::loadOverlay() {
f.read(&_data[0], dataSize);
}
-void Map::getData() {
- // TODO
-}
-
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index abc5a0c1daf..9fb765487b3 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -97,12 +97,6 @@ public:
byte &operator[](uint ofs) {
return _data[ofs];
}
-
- /**
- * Loads some common data values from the map's
- * data segment into fields
- */
- void getData();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 8ca6663704e..3758b32f800 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -68,7 +68,7 @@ void Maps::select(byte section, byte id1, byte id2) {
void Maps::display(byte id1, byte id2, byte section) {
select(section, id1, id2);
- _currentMap->getData();
+ loadTiles();
g_events->msgGame(GameMessage("DISPLAY"));
}
@@ -85,6 +85,10 @@ uint Maps::getIndex(byte section, byte id1, byte id2) {
return idx;
}
+void Maps::loadTiles() {
+ // TODO
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index d12218cf5f2..9b0d12abfc2 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -169,6 +169,11 @@ private:
* Gets the index of a map given the id values
*/
uint getIndex(byte section, byte v1, byte v2);
+
+ /**
+ * Loads tile graphics needed for rendering the 3d view
+ */
+ void loadTiles();
public:
uint _mapId = (uint)-1;
Common::Point _mapPos;
Commit: 1505833b61c7401dca32c648ca42f1a729c61f12
https://github.com/scummvm/scummvm/commit/1505833b61c7401dca32c648ca42f1a729c61f12
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:46+01:00
Commit Message:
MM: MM1: Add town loading method
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/globals.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game.h
engines/mm/mm1/views/inn.cpp
engines/mm/mm1/views/main_menu.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 5685fb95207..4b07b0ef9a1 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -216,7 +216,6 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
- MESSAGE(Game);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index f06def68e9a..7b4d31d2ad9 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -38,7 +38,7 @@ public:
Roster _roster;
const Graphics::Font *_font = nullptr;
Character *_currCharacter = nullptr;
- int _startingTown = 0;
+ Maps::TownId _startingTown = Maps::SORPIGAL;
IntArray _partyChars;
Maps::Maps _maps;
public:
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 3758b32f800..e82d694e19b 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -61,19 +61,85 @@ void Maps::load(uint mapId) {
Common::fill(&_data1[0], &_data1[32], 0);
}
-void Maps::select(byte section, byte id1, byte id2) {
- uint mapId = getIndex(section, id1, id2);
+void Maps::select(uint16 id, byte section) {
+ uint mapId = getIndex(id, section);
load(mapId);
}
-void Maps::display(byte id1, byte id2, byte section) {
- select(section, id1, id2);
+void Maps::display(uint16 id, byte section) {
+ select(id, section);
loadTiles();
g_events->msgGame(GameMessage("DISPLAY"));
}
-uint Maps::getIndex(byte section, byte id1, byte id2) {
- uint16 id = MKTAG16(id2, id1);
+void Maps::loadTown(TownId townId) {
+ switch (townId) {
+ case SORPIGAL:
+ town15setup();
+ _mapPos = Common::Point(8, 3);
+ display(0x604);
+ break;
+
+ case PORTSMITH:
+ town23setup();
+ _mapPos = Common::Point(3, 12);
+ display(0xc03);
+ break;
+
+ case ALGARY:
+ town23setup();
+ _mapPos = Common::Point(14, 8);
+ display(0x302);
+ break;
+
+ case DUSK:
+ town4setup();
+ _mapPos = Common::Point(11, 8);
+ display(0x802);
+ break;
+
+ case ERLIQUIN:
+ town15setup();
+ _mapPos = Common::Point(4, 4);
+ display(0xB1A);
+ break;
+ }
+}
+
+void Maps::town15setup() {
+ _mapDirectionMask = DIRMASK_N;
+ _val1 = 3;
+ _val2 = 0x30;
+ _val3 = 0xC;
+ _val4 = 0x10;
+ _val5 = 0xff;
+ _val6 = 1;
+ _val7 = 0xf0;
+}
+
+void Maps::town23setup() {
+ _mapDirectionMask = DIRMASK_W;
+ _val1 = 0xC;
+ _val2 = 0xC0;
+ _val3 = 0x30;
+ _val4 = 0xff;
+ _val5 = 0xf0;
+ _val6 = 0x10;
+ _val7 = 1;
+}
+
+void Maps::town4setup() {
+ _mapDirectionMask = DIRMASK_E;
+ _val1 = 0xc0;
+ _val2 = 0xC;
+ _val3 = 3;
+ _val4 = 1;
+ _val5 = 0x10;
+ _val6 = 0xf0;
+ _val7 = 0xff;
+}
+
+uint Maps::getIndex(uint16 id, byte section) {
uint idx = LOOKUPS_START[section / 2];
// Find map by Id
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 9b0d12abfc2..c4d275c34e2 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -30,6 +30,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+enum TownId {
+ SORPIGAL = 1, PORTSMITH = 2, ALGARY = 3,
+ DUSK = 4, ERLIQUIN = 5
+};
+
+enum DirMask {
+ DIRMASK_NONE = 0,
+ DIRMASK_N = 0xC0, DIRMASK_E = 0x30,
+ DIRMASK_S = 0xC, DIRMASK_W = 3
+};
+
/** PLACEHOLDER MAPS **/
#define PLACEHOLDER(INDEX, NAME, ID) \
class Map##INDEX : public Map { \
@@ -168,19 +179,38 @@ private:
/**
* Gets the index of a map given the id values
*/
- uint getIndex(byte section, byte v1, byte v2);
+ uint getIndex(uint16 id, byte section);
/**
* Loads tile graphics needed for rendering the 3d view
*/
void loadTiles();
+
+ /**
+ * Town setup for SORPIGAL & ERLIQUIN
+ */
+ void town15setup();
+
+ /**
+ * Town setup for PORTSMITH and ALGARY
+ */
+ void town23setup();
+
+ /**
+ * Town setup for DUSK
+ */
+ void town4setup();
+
public:
uint _mapId = (uint)-1;
Common::Point _mapPos;
- byte _mapDirectionMask = 0;
+ DirMask _mapDirectionMask = DIRMASK_NONE;
Map *_currentMap = nullptr;
byte _data1[32];
int _colorOffset = 0;
+ int _val1 = 0, _val2 = 0, _val3 = 0, _val4 = 0;
+ int _val5 = 0, _val6 = 0, _val7 = 0;
+
public:
Maps();
@@ -192,12 +222,17 @@ public:
/**
* Selects a map
*/
- void select(byte section, byte id1, byte id2);
+ void select(uint16 id, byte section);
/**
* Selects a map, and switches to in-game display
*/
- void display(byte id1, byte id2, byte section = 1);
+ void display(uint16 id, byte section = 1);
+
+ /**
+ * Loads a town
+ */
+ void loadTown(TownId townId);
/**
* Get a given map
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 458dafcecab..3e6f7e05a12 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -52,6 +52,15 @@ bool Game::msgKeypress(const KeypressMessage &msg) {
return true;
}
+bool Game::msgGame(const GameMessage &msg) {
+ if (msg._name == "DISPLAY") {
+ replaceView(this);
+ return true;
+ }
+
+ return TextView::msgGame(msg);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game.h b/engines/mm/mm1/views/game.h
index 5da37c65a4b..860123a513c 100644
--- a/engines/mm/mm1/views/game.h
+++ b/engines/mm/mm1/views/game.h
@@ -44,6 +44,7 @@ public:
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgGame(const GameMessage &msg) override;
};
} // namespace Views
diff --git a/engines/mm/mm1/views/inn.cpp b/engines/mm/mm1/views/inn.cpp
index ff42c8baf72..09c19e6c8ad 100644
--- a/engines/mm/mm1/views/inn.cpp
+++ b/engines/mm/mm1/views/inn.cpp
@@ -110,9 +110,8 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
g_globals->_party.push_back(
g_globals->_roster[g_globals->_partyChars[i]]);
- // TODO: town setup
- // Switch to game view
- replaceView("Game");
+ // Load the given town
+ g_globals->_maps.loadTown(g_globals->_startingTown);
}
return false;
diff --git a/engines/mm/mm1/views/main_menu.cpp b/engines/mm/mm1/views/main_menu.cpp
index 0af3c7aa317..9ecb8617397 100644
--- a/engines/mm/mm1/views/main_menu.cpp
+++ b/engines/mm/mm1/views/main_menu.cpp
@@ -56,7 +56,8 @@ bool MainMenu::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_3:
case Common::KEYCODE_4:
case Common::KEYCODE_5:
- g_globals->_startingTown = msg.keycode - Common::KEYCODE_0;
+ g_globals->_startingTown = (Maps::TownId)(
+ msg.keycode - Common::KEYCODE_0);
replaceView("Inn");
break;
Commit: 2d1f2b7831e6892d777f8f4cf8575886ea1c6231
https://github.com/scummvm/scummvm/commit/2d1f2b7831e6892d777f8f4cf8575886ea1c6231
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: First wallpix tile being correctly decoded
Changed paths:
A engines/mm/mm1/gfx/dta.cpp
A engines/mm/mm1/gfx/dta.h
engines/mm/mm1/events.cpp
engines/mm/mm1/gfx/screen_decoder.cpp
engines/mm/mm1/gfx/screen_decoder.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index ce033bd266c..76e1b9f38c6 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -44,12 +44,13 @@ Events::~Events() {
void Events::runGame() {
Views::Dialogs dialogsContainer; // Load up all the dialogs
- // Run the game
- addView("MainMenu");
-
uint currTime, nextFrameTime = 0;
_screen = new Graphics::Screen();
+ // Run the game
+ g_globals->_maps.loadTown(Maps::SORPIGAL);
+ //addView("Title");
+
Common::Event e;
for (;;) {
while (g_system->getEventManager()->pollEvent(e)) {
diff --git a/engines/mm/mm1/gfx/dta.cpp b/engines/mm/mm1/gfx/dta.cpp
new file mode 100644
index 00000000000..aa7c7c69a4c
--- /dev/null
+++ b/engines/mm/mm1/gfx/dta.cpp
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "mm/mm1/gfx/dta.h"
+#include "mm/mm1/gfx/screen_decoder.h"
+
+namespace MM {
+namespace MM1 {
+namespace Gfx {
+
+Common::SeekableReadStream *DTA::load(uint entryIndex) {
+ Common::File f;
+
+ if (!f.open(_fname))
+ error("Could not open - %s", _fname.c_str());
+
+ uint indexSize = f.readUint16LE();
+ assert(entryIndex < (indexSize / 4));
+ f.seek(entryIndex * 4, SEEK_CUR);
+ size_t entryOffset = f.readUint32LE();
+ size_t nextOffset = (entryIndex == (indexSize / 4 - 1)) ?
+ f.size() : f.readUint32LE();
+
+ f.seek(2 + indexSize + entryOffset);
+ return f.readStream(nextOffset - entryOffset);
+}
+
+} // namespace Gfx
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/gfx/dta.h b/engines/mm/mm1/gfx/dta.h
new file mode 100644
index 00000000000..938e73403a4
--- /dev/null
+++ b/engines/mm/mm1/gfx/dta.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GFX_DTA_H
+#define MM1_GFX_DTA_H
+
+#include "graphics/managed_surface.h"
+
+namespace MM {
+namespace MM1 {
+namespace Gfx {
+
+#define WALLPIX_DTA "wallpix.dta"
+#define MONPIX_DTA "monpix.dta"
+
+class DTA {
+public:
+ Common::String _fname;
+public:
+ DTA(const Common::String &fname) : _fname(fname) {
+ }
+
+ /**
+ * Returns a read stream for an entry
+ */
+ Common::SeekableReadStream *load(uint entryIndex);
+};
+
+} // namespace Gfx
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/gfx/screen_decoder.cpp b/engines/mm/mm1/gfx/screen_decoder.cpp
index b2d55f5507a..c6002569cbb 100644
--- a/engines/mm/mm1/gfx/screen_decoder.cpp
+++ b/engines/mm/mm1/gfx/screen_decoder.cpp
@@ -36,52 +36,58 @@ void ScreenDecoder::destroy() {
_surface.free();
}
-bool ScreenDecoder::loadFile(const Common::String &fname) {
+bool ScreenDecoder::loadFile(const Common::String &fname,
+ int16 w, int16 h) {
Common::File f;
- return f.open(fname) && loadStream(f);
+ return f.open(fname) && loadStream(f, w, h);
}
-bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream) {
+bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
+ int16 w, int16 h) {
byte bytes[IMAGE_SIZE];
byte v;
int len;
const byte *srcP;
byte *destP = &bytes[0];
int index = 0;
+ int imgSize = w * h / 4;
- int size = stream.readUint16LE();
- if (size < 0 || size > stream.size())
- return false;
+ if (_size == -1)
+ _size = stream.readUint16LE();
+ assert(_size < IMAGE_SIZE);
// Decompress the image bytes
- while (size > 0) {
+ int x = 0;
+ while (x < (w / 4) && !stream.eos()) {
v = stream.readByte();
if (v != 0x7B) {
len = 1;
- --size;
+ --_size;
} else {
len = stream.readByte() + 1;
v = stream.readByte();
- size -= 3;
+ _size -= 3;
}
for (; len > 0; --len) {
destP[index] = v;
- index += 80;
- if (index >= IMAGE_SIZE) {
+ index += (w / 4);
+ if (index >= imgSize) {
index = 0;
++destP;
+ ++x;
}
}
}
- // Create surface from splitting up the nibbles
- _surface.create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
+ // Create surface from splitting up the pairs of bits
+ _surface.free();
+ _surface.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
srcP = &bytes[0];
destP = (byte *)_surface.getPixels();
- for (size_t i = 0; i < IMAGE_SIZE; ++i, ++srcP) {
+ for (int i = 0; i < w * h / 4; ++i, ++srcP) {
v = *srcP;
for (int j = 0; j < 4; ++j, v <<= 2)
*destP++ = v >> 6;
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
index 8d375419ad0..db0f76503f0 100644
--- a/engines/mm/mm1/gfx/screen_decoder.h
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -31,20 +31,30 @@ namespace Gfx {
class ScreenDecoder : public Image::ImageDecoder {
private:
+ int _size = -1;
Graphics::Surface _surface;
public:
ScreenDecoder() {}
~ScreenDecoder() override;
void destroy() override;
- bool loadFile(const Common::String &fname);
- bool loadStream(Common::SeekableReadStream &stream) override;
+ bool loadFile(const Common::String &fname,
+ int16 w = 320, int16 h = 200);
+ bool loadStream(Common::SeekableReadStream &stream, int16 w, int16 h);
+ bool loadStream(Common::SeekableReadStream &stream) {
+ return loadStream(stream, 320, 200);
+ }
+
const Graphics::Surface *getSurface() const override {
return &_surface;
}
const byte *getPalette() const override { return nullptr; }
uint16 getPaletteColorCount() const override { return 0; }
void clear() { _surface.free(); }
+
+ bool finished() const {
+ return _size == 0;
+ }
};
} // namespace Gfx
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 9fb765487b3..3a1c69630af 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -97,6 +97,12 @@ public:
byte &operator[](uint ofs) {
return _data[ofs];
}
+ byte dataByte(uint ofs) const {
+ return _data[ofs];
+ }
+ uint16 dataWord(uint16 ofs) const {
+ return (uint16)_data[ofs] | ((uint16)_data[ofs + 1] << 8);
+ }
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index e82d694e19b..1efa91ebc92 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -20,15 +20,19 @@
*/
#include "common/endian.h"
+#include "common/stream.h"
#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/gfx/dta.h"
+#include "mm/mm1/gfx/screen_decoder.h"
#include "mm/mm1/events.h"
+#include "common/system.h"
namespace MM {
namespace MM1 {
namespace Maps {
-static byte LOOKUPS_START[4] = { 0, 0, 14, 34 };
-static byte COLOR_OFFSET[55] = {
+static const byte LOOKUPS_START[4] = { 0, 0, 14, 34 };
+static const byte COLOR_OFFSET[55] = {
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -36,6 +40,27 @@ static byte COLOR_OFFSET[55] = {
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
};
+static const uint16 TILE_AREA1[] = {
+ 0x10D, 0x0B0B, 0x50A, 0x11A, 0x0B18, 0x517
+};
+static const uint16 TILE_AREA2[] = {
+ 0xB0B, 0x50A, 0x10D, 0x0F08, 0x907, 0x11A, 0x0B18, 0x517
+};
+static const uint16 TILE_AREA3[] = {
+ 0xB0B, 0x10D, 0x517, 0x0B18, 0x11A, 0x50A
+};
+
+static const uint16 *TILE_AREAS[3] = { TILE_AREA1, TILE_AREA2, TILE_AREA3 };
+static const byte TILE_OFFSET[3] = { 1, 7, 15 };
+
+static const uint16 TILE_WIDTHS[] = {
+ 32, 40, 24, 16, 32, 40, 24, 16, 176, 96, 48, 16
+};
+static const uint16 TILE_HEIGHTS[] = {
+ 128, 96, 64, 32, 128, 96, 64, 32, 96, 64, 32, 16
+};
+
+
Maps::Maps() :
_map00(this), _map01(this), _map02(this), _map03(this),
_map04(this), _map05(this), _map06(this), _map07(this),
@@ -152,7 +177,56 @@ uint Maps::getIndex(uint16 id, byte section) {
}
void Maps::loadTiles() {
- // TODO
+ _loadArea = _currentMap->dataByte(1);
+ _loadId = _currentMap->dataWord(2);
+ _loadSection = 1;
+ loadTile();
+
+ _loadArea = _currentMap->dataByte(1);
+ _loadId = _currentMap->dataWord(4);
+ _loadSection = 2;
+ loadTile();
+
+ _loadArea = _currentMap->dataByte(1);
+ _loadId = _currentMap->dataWord(6);
+ _loadSection = 3;
+ loadTile();
+}
+
+void Maps::loadTile() {
+ assert(_loadArea >= 1 && _loadArea <= 3);
+ const uint16 *arr = TILE_AREAS[_loadArea - 1];
+ int ctr = TILE_OFFSET[_loadArea - 1];
+ int entryIndex;
+
+ for (; *arr != _loadId; ++arr, ++ctr) {
+ }
+
+ _loadFlag = 0xff;
+ if (ctr >= 19) {
+ if (ctr != 19)
+ _loadFlag = 0xaa;
+ ctr = 1;
+ }
+
+ // Get the entry from the wallpix.dta file
+ entryIndex = ctr - 1;
+ Gfx::DTA dta(WALLPIX_DTA);
+ Common::SeekableReadStream *entry = dta.load(entryIndex);
+
+ // ***DEBUG*** - Display the first tile of stream
+ Gfx::ScreenDecoder decoder;
+
+ if (decoder.loadStream(*entry, 32, 128)) {
+ Graphics::Screen &scr = *g_events->getScreen();
+ scr.blitFrom(decoder.getSurface());
+
+ scr.update();
+ Common::Event e;
+ g_system->getEventManager()->pollEvent(e);
+ }
+
+ delete entry;
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index c4d275c34e2..0dd45c28bdd 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -185,6 +185,7 @@ private:
* Loads tile graphics needed for rendering the 3d view
*/
void loadTiles();
+ void loadTile();
/**
* Town setup for SORPIGAL & ERLIQUIN
@@ -210,7 +211,10 @@ public:
int _colorOffset = 0;
int _val1 = 0, _val2 = 0, _val3 = 0, _val4 = 0;
int _val5 = 0, _val6 = 0, _val7 = 0;
-
+ int _loadId = 0;
+ int _loadArea = 0;
+ int _loadSection = 0;
+ byte _loadFlag = 0;
public:
Maps();
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 7fbbc33abdb..709daed4998 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS := \
mm1/data/char.o \
mm1/data/game_state.o \
mm1/data/roster.o \
+ mm1/gfx/dta.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
mm1/utils/strings.o \
Commit: 6408139ea2827b927ab7ac1fb2fb28c52c116d1c
https://github.com/scummvm/scummvm/commit/6408139ea2827b927ab7ac1fb2fb28c52c116d1c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: Improve image decoder for tile loading
Changed paths:
engines/mm/mm1/gfx/screen_decoder.cpp
engines/mm/mm1/gfx/screen_decoder.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/gfx/screen_decoder.cpp b/engines/mm/mm1/gfx/screen_decoder.cpp
index c6002569cbb..77de9ce683e 100644
--- a/engines/mm/mm1/gfx/screen_decoder.cpp
+++ b/engines/mm/mm1/gfx/screen_decoder.cpp
@@ -39,7 +39,11 @@ void ScreenDecoder::destroy() {
bool ScreenDecoder::loadFile(const Common::String &fname,
int16 w, int16 h) {
Common::File f;
- return f.open(fname) && loadStream(f, w, h);
+ if (!f.open(fname))
+ return false;
+
+ f.skip(2); // Skip size word
+ return loadStream(f, w, h);
}
bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
@@ -52,21 +56,15 @@ bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
int index = 0;
int imgSize = w * h / 4;
- if (_size == -1)
- _size = stream.readUint16LE();
- assert(_size < IMAGE_SIZE);
-
// Decompress the image bytes
int x = 0;
while (x < (w / 4) && !stream.eos()) {
v = stream.readByte();
if (v != 0x7B) {
len = 1;
- --_size;
} else {
len = stream.readByte() + 1;
v = stream.readByte();
- _size -= 3;
}
for (; len > 0; --len) {
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
index db0f76503f0..86446b5e589 100644
--- a/engines/mm/mm1/gfx/screen_decoder.h
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -31,7 +31,6 @@ namespace Gfx {
class ScreenDecoder : public Image::ImageDecoder {
private:
- int _size = -1;
Graphics::Surface _surface;
public:
ScreenDecoder() {}
@@ -51,10 +50,6 @@ public:
const byte *getPalette() const override { return nullptr; }
uint16 getPaletteColorCount() const override { return 0; }
void clear() { _surface.free(); }
-
- bool finished() const {
- return _size == 0;
- }
};
} // namespace Gfx
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 1efa91ebc92..6e2b77a9334 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -53,10 +53,11 @@ static const uint16 TILE_AREA3[] = {
static const uint16 *TILE_AREAS[3] = { TILE_AREA1, TILE_AREA2, TILE_AREA3 };
static const byte TILE_OFFSET[3] = { 1, 7, 15 };
-static const uint16 TILE_WIDTHS[] = {
+#define RESOURCE_TILES_COUNT 12
+static const uint16 TILE_WIDTHS[RESOURCE_TILES_COUNT] = {
32, 40, 24, 16, 32, 40, 24, 16, 176, 96, 48, 16
};
-static const uint16 TILE_HEIGHTS[] = {
+static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
128, 96, 64, 32, 128, 96, 64, 32, 96, 64, 32, 16
};
@@ -213,20 +214,29 @@ void Maps::loadTile() {
entryIndex = ctr - 1;
Gfx::DTA dta(WALLPIX_DTA);
Common::SeekableReadStream *entry = dta.load(entryIndex);
+ entry->skip(2);
- // ***DEBUG*** - Display the first tile of stream
- Gfx::ScreenDecoder decoder;
+ // Decode the tiles
+ Common::Array<Graphics::ManagedSurface> &tiles =
+ _tiles[_loadSection - 1];
+ tiles.clear();
+ tiles.resize(RESOURCE_TILES_COUNT);
- if (decoder.loadStream(*entry, 32, 128)) {
- Graphics::Screen &scr = *g_events->getScreen();
- scr.blitFrom(decoder.getSurface());
+ Gfx::ScreenDecoder decoder;
+ for (int i = 0; i < RESOURCE_TILES_COUNT; ++i) {
+ if (!decoder.loadStream(*entry,
+ TILE_WIDTHS[i], TILE_HEIGHTS[i]))
+ error("Failed decoding tile");
- scr.update();
- Common::Event e;
- g_system->getEventManager()->pollEvent(e);
+ tiles[i].copyFrom(decoder.getSurface());
}
- delete entry;
+ // ***DEBUG*** - Display the first tile of stream
+ Graphics::Screen &scr = *g_events->getScreen();
+ scr.blitFrom(_tiles[_loadSection - 1].front());
+ scr.update();
+ Common::Event e;
+ g_system->getEventManager()->pollEvent(e);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 0dd45c28bdd..97b3e951e8a 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -24,6 +24,7 @@
#include "common/array.h"
#include "common/rect.h"
+#include "graphics/managed_surface.h"
#include "mm/mm1/maps/map00.h"
namespace MM {
@@ -203,6 +204,7 @@ private:
void town4setup();
public:
+ Common::Array<Graphics::ManagedSurface> _tiles[3];
uint _mapId = (uint)-1;
Common::Point _mapPos;
DirMask _mapDirectionMask = DIRMASK_NONE;
Commit: 0708c63916e28c28029606085d5ef8b920283d0c
https://github.com/scummvm/scummvm/commit/0708c63916e28c28029606085d5ef8b920283d0c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: Figured out map direction bitmasks and offsets
Changed paths:
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 6e2b77a9334..91a3deb3b3d 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -133,36 +133,39 @@ void Maps::loadTown(TownId townId) {
}
void Maps::town15setup() {
- _mapDirectionMask = DIRMASK_N;
- _val1 = 3;
- _val2 = 0x30;
- _val3 = 0xC;
- _val4 = 0x10;
- _val5 = 0xff;
- _val6 = 1;
- _val7 = 0xf0;
+ _forwardsMask = DIRMASK_N;
+ _leftMask = DIRMASK_W;
+ _rightMask = DIRMASK_E;
+ _backwardsMask = DIRMASK_S;
+
+ _forwardOffset = MAP_W;
+ _leftOffset = -1;
+ _rightOffset = 1;
+ _backOffset = -MAP_W;
}
void Maps::town23setup() {
- _mapDirectionMask = DIRMASK_W;
- _val1 = 0xC;
- _val2 = 0xC0;
- _val3 = 0x30;
- _val4 = 0xff;
- _val5 = 0xf0;
- _val6 = 0x10;
- _val7 = 1;
+ _forwardsMask = DIRMASK_W;
+ _leftMask = DIRMASK_S;
+ _rightMask = DIRMASK_N;
+ _backwardsMask = DIRMASK_E;
+
+ _forwardOffset = -1;
+ _leftOffset = -MAP_W;
+ _rightOffset = MAP_W;
+ _backOffset = 1;
}
void Maps::town4setup() {
- _mapDirectionMask = DIRMASK_E;
- _val1 = 0xc0;
- _val2 = 0xC;
- _val3 = 3;
- _val4 = 1;
- _val5 = 0x10;
- _val6 = 0xf0;
- _val7 = 0xff;
+ _forwardsMask = DIRMASK_E;
+ _leftMask = DIRMASK_N;
+ _rightMask = DIRMASK_S;
+ _backwardsMask = DIRMASK_W;
+
+ _forwardOffset = 1;
+ _leftOffset = MAP_W;
+ _rightOffset = -MAP_W;
+ _backOffset = -1;
}
uint Maps::getIndex(uint16 id, byte section) {
@@ -230,13 +233,6 @@ void Maps::loadTile() {
tiles[i].copyFrom(decoder.getSurface());
}
-
- // ***DEBUG*** - Display the first tile of stream
- Graphics::Screen &scr = *g_events->getScreen();
- scr.blitFrom(_tiles[_loadSection - 1].front());
- scr.update();
- Common::Event e;
- g_system->getEventManager()->pollEvent(e);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 97b3e951e8a..ae3897128d0 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -37,7 +37,6 @@ enum TownId {
};
enum DirMask {
- DIRMASK_NONE = 0,
DIRMASK_N = 0xC0, DIRMASK_E = 0x30,
DIRMASK_S = 0xC, DIRMASK_W = 3
};
@@ -207,12 +206,16 @@ public:
Common::Array<Graphics::ManagedSurface> _tiles[3];
uint _mapId = (uint)-1;
Common::Point _mapPos;
- DirMask _mapDirectionMask = DIRMASK_NONE;
Map *_currentMap = nullptr;
byte _data1[32];
int _colorOffset = 0;
- int _val1 = 0, _val2 = 0, _val3 = 0, _val4 = 0;
- int _val5 = 0, _val6 = 0, _val7 = 0;
+
+ DirMask _forwardsMask = DIRMASK_N,
+ _leftMask = DIRMASK_W,
+ _rightMask = DIRMASK_E,
+ _backwardsMask = DIRMASK_S;
+ int8 _forwardOffset = 0, _leftOffset = 0;
+ int8 _rightOffset = 0, _backOffset = 0;
int _loadId = 0;
int _loadArea = 0;
int _loadSection = 0;
Commit: 080866c4843b2372bcad22c1deb841ab917859c1
https://github.com/scummvm/scummvm/commit/080866c4843b2372bcad22c1deb841ab917859c1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: Beginnings of game view class
Changed paths:
A engines/mm/mm1/views/game_view.cpp
A engines/mm/mm1/views/game_view.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/game.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 91a3deb3b3d..1fd1b8e036d 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -133,7 +133,7 @@ void Maps::loadTown(TownId townId) {
}
void Maps::town15setup() {
- _forwardsMask = DIRMASK_N;
+ _forwardMask = DIRMASK_N;
_leftMask = DIRMASK_W;
_rightMask = DIRMASK_E;
_backwardsMask = DIRMASK_S;
@@ -141,11 +141,11 @@ void Maps::town15setup() {
_forwardOffset = MAP_W;
_leftOffset = -1;
_rightOffset = 1;
- _backOffset = -MAP_W;
+ _backwardsOffset = -MAP_W;
}
void Maps::town23setup() {
- _forwardsMask = DIRMASK_W;
+ _forwardMask = DIRMASK_W;
_leftMask = DIRMASK_S;
_rightMask = DIRMASK_N;
_backwardsMask = DIRMASK_E;
@@ -153,11 +153,11 @@ void Maps::town23setup() {
_forwardOffset = -1;
_leftOffset = -MAP_W;
_rightOffset = MAP_W;
- _backOffset = 1;
+ _backwardsOffset = 1;
}
void Maps::town4setup() {
- _forwardsMask = DIRMASK_E;
+ _forwardMask = DIRMASK_E;
_leftMask = DIRMASK_N;
_rightMask = DIRMASK_S;
_backwardsMask = DIRMASK_W;
@@ -165,7 +165,7 @@ void Maps::town4setup() {
_forwardOffset = 1;
_leftOffset = MAP_W;
_rightOffset = -MAP_W;
- _backOffset = -1;
+ _backwardsOffset = -1;
}
uint Maps::getIndex(uint16 id, byte section) {
@@ -235,6 +235,42 @@ void Maps::loadTile() {
}
}
+void Maps::turnLeft() {
+ DirMask tempMask = _rightMask;
+ _rightMask = _forwardMask;
+ _forwardMask = _leftMask;
+ _leftMask = _backwardsMask;
+ _backwardsMask = tempMask;
+
+ int8 tempOffset = _rightOffset;
+ _rightOffset = _forwardOffset;
+ _forwardOffset = _leftOffset;
+ _leftOffset = _backwardsOffset;
+ _backwardsOffset = tempOffset;
+}
+
+void Maps::turnRight() {
+ DirMask tempMask = _leftMask;
+ _leftMask = _forwardMask;
+ _forwardMask = _rightMask;
+ _rightMask = _backwardsMask;
+ _backwardsMask = tempMask;
+
+ int8 tempOffset = _leftOffset;
+ _leftOffset = _forwardOffset;
+ _forwardOffset = _rightOffset;
+ _rightOffset = _backwardsOffset;
+ _backwardsOffset = tempOffset;
+}
+
+void Maps::forward() {
+
+}
+
+void Maps::backwards() {
+
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index ae3897128d0..84ce9349aa5 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -210,12 +210,12 @@ public:
byte _data1[32];
int _colorOffset = 0;
- DirMask _forwardsMask = DIRMASK_N,
+ DirMask _forwardMask = DIRMASK_N,
_leftMask = DIRMASK_W,
_rightMask = DIRMASK_E,
_backwardsMask = DIRMASK_S;
int8 _forwardOffset = 0, _leftOffset = 0;
- int8 _rightOffset = 0, _backOffset = 0;
+ int8 _rightOffset = 0, _backwardsOffset = 0;
int _loadId = 0;
int _loadArea = 0;
int _loadSection = 0;
@@ -247,6 +247,26 @@ public:
* Get a given map
*/
Map *getMap(uint mapId) const { return _maps[mapId]; }
+
+ /**
+ * Turn left
+ */
+ void turnLeft();
+
+ /**
+ * Turn right
+ */
+ void turnRight();
+
+ /**
+ * Move forward
+ */
+ void forward();
+
+ /**
+ * Move backwards
+ */
+ void backwards();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/game.h b/engines/mm/mm1/views/game.h
index 860123a513c..b84cf900c6e 100644
--- a/engines/mm/mm1/views/game.h
+++ b/engines/mm/mm1/views/game.h
@@ -26,6 +26,7 @@
#include "mm/mm1/views/game_commands.h"
#include "mm/mm1/views/game_messages.h"
#include "mm/mm1/views/game_party.h"
+#include "mm/mm1/views/game_view.h"
namespace MM {
namespace MM1 {
@@ -36,6 +37,7 @@ private:
GameCommands _commands;
GameMessages _messages;
GameParty _party;
+ GameView _view;
public:
Game();
virtual ~Game() {}
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
new file mode 100644
index 00000000000..5dd3c83ad5f
--- /dev/null
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/game_view.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+GameView::GameView() : TextView("View") {
+}
+
+void GameView::draw() {
+
+}
+
+bool GameView::msgAction(const ActionMessage &msg) {
+ switch (msg._action) {
+ case KEYBIND_FORWARDS:
+ forward();
+ break;
+ case KEYBIND_BACKWARDS:
+ backwards();
+ break;
+ case KEYBIND_TURN_LEFT:
+ turnLeft();
+ break;
+ case KEYBIND_TURN_RIGHT:
+ turnRight();
+ break;
+ default:
+ return TextView::msgAction(msg);
+ }
+
+ return true;
+}
+
+bool GameView::msgGame(const GameMessage &msg) {
+ /*
+ if (msg._name == "DISPLAY") {
+ replaceView(this);
+ return true;
+ }
+ */
+
+ return TextView::msgGame(msg);
+}
+
+void GameView::turnLeft() {
+ g_globals->_maps.turnLeft();
+}
+
+void GameView::turnRight() {
+ g_globals->_maps.turnRight();
+}
+
+void GameView::forward() {
+ g_globals->_maps.forward();
+}
+
+void GameView::backwards() {
+ g_globals->_maps.backwards();
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
new file mode 100644
index 00000000000..df4b4910bf0
--- /dev/null
+++ b/engines/mm/mm1/views/game_view.h
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_GAME_VIEW_H
+#define MM1_VIEWS_GAME_VIEW_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class GameView : public TextView {
+private:
+ /**
+ * Turn left
+ */
+ void turnLeft();
+
+ /**
+ * Turn right
+ */
+ void turnRight();
+
+ /**
+ * Move forwards
+ */
+ void forward();
+
+ /**
+ * Move backwards
+ */
+ void backwards();
+
+public:
+ GameView();
+ virtual ~GameView() {}
+
+ void draw() override;
+ bool msgGame(const GameMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 709daed4998..c26579a19fd 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -22,6 +22,7 @@ MODULE_OBJS := \
mm1/views/game_commands.o \
mm1/views/game_messages.o \
mm1/views/game_party.o \
+ mm1/views/game_view.o \
mm1/views/inn.o \
mm1/views/main_menu.o \
mm1/views/protect.o \
Commit: 93a17c392a39825abc5dff5108701cfdac46e277
https://github.com/scummvm/scummvm/commit/93a17c392a39825abc5dff5108701cfdac46e277
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: Make the spells array a structure for easier access
Changed paths:
engines/mm/mm1/data/game_state.cpp
engines/mm/mm1/data/game_state.h
engines/mm/mm1/views/protect.cpp
diff --git a/engines/mm/mm1/data/game_state.cpp b/engines/mm/mm1/data/game_state.cpp
index af57cc50b0d..7e3ca0ca2f8 100644
--- a/engines/mm/mm1/data/game_state.cpp
+++ b/engines/mm/mm1/data/game_state.cpp
@@ -26,7 +26,7 @@ namespace MM {
namespace MM1 {
GameState::GameState() {
- Common::fill(&_activeSpells[0], &_activeSpells[ACTIVE_SPELLS_COUNT], 0);
+ Common::fill(&_spells._arr[0], &_spells._arr[ACTIVE_SPELLS_COUNT], 0);
}
} // namespace MM1
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index 67182f09795..3ab55958207 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -32,13 +32,39 @@ namespace MM1 {
#define ACTIVE_SPELLS_COUNT 18
+struct ActiveSpellsStruct {
+ byte fear;
+ byte cold;
+ byte fire;
+ byte poison;
+ byte acid;
+ byte elec;
+ byte magic;
+ byte light;
+ byte leather_skin;
+ byte levitate;
+ byte walk_on_water;
+ byte guard_dog;
+ byte psychic_protecti;
+ byte bless;
+ byte invisbility;
+ byte shield;
+ byte power_shield;
+ byte cursed;
+};
+
+union ActiveSpells {
+ ActiveSpellsStruct _s;
+ byte _arr[ACTIVE_SPELLS_COUNT];
+};
+
/**
* This acts as a container for everything in the game
* that is persisted to savegames
*/
struct GameState {
Common::Array<Character> _party;
- uint _activeSpells[ACTIVE_SPELLS_COUNT];
+ ActiveSpells _spells;
GameState();
};
diff --git a/engines/mm/mm1/views/protect.cpp b/engines/mm/mm1/views/protect.cpp
index 743fe4373c3..45c92be7133 100644
--- a/engines/mm/mm1/views/protect.cpp
+++ b/engines/mm/mm1/views/protect.cpp
@@ -35,7 +35,7 @@ void Protect::draw() {
_textPos.x = 0;
_textPos.y = 2;
for (int i = 0; i < 7; ++i) {
- if (g_globals->_activeSpells[i]) {
+ if (g_globals->_spells._arr[i]) {
printProtectionFrom();
writeString(STRING[Common::String::format(
"dialogs.protect.%d", i + 1)]);
@@ -44,9 +44,9 @@ void Protect::draw() {
}
// Light spell
- if (g_globals->_activeSpells[7]) {
+ if (g_globals->_spells._arr[7]) {
writeString(STRING["dialogs.protect.8"]);
- writeNumber(g_globals->_activeSpells[7]);
+ writeNumber(g_globals->_spells._arr[7]);
writeChar(')');
newLine();
}
@@ -56,7 +56,7 @@ void Protect::draw() {
if (i == 13)
newLine();
- if (g_globals->_activeSpells[i]) {
+ if (g_globals->_spells._arr[i]) {
writeString(STRING[Common::String::format(
"dialogs.protect.%d", i + 1)]);
newLine();
@@ -66,8 +66,8 @@ void Protect::draw() {
--_textPos.y;
_textPos.x = 13;
- if (g_globals->_activeSpells[17]) {
- writeNumber(g_globals->_activeSpells[17]);
+ if (g_globals->_spells._arr[17]) {
+ writeNumber(g_globals->_spells._arr[17]);
_textPos.x++;
writeString(STRING["dialogs.protect.to_attacks"]);
}
@@ -83,7 +83,7 @@ void Protect::printProtectionLevel(uint protectIndex) {
_textPos.x = 24;
writeChar('+');
_textPos.x++;
- writeNumber(g_globals->_activeSpells[protectIndex]);
+ writeNumber(g_globals->_spells._arr[protectIndex]);
writeChar('%');
newLine();
}
Commit: 5eb0e9d9a609cf3f632f1d407e47de95b718856d
https://github.com/scummvm/scummvm/commit/5eb0e9d9a609cf3f632f1d407e47de95b718856d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: In-progress 3d view drawing code
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 980524548a0..6f62bcc3f57 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -439,3 +439,13 @@ maps:
cdb9: "JAIL. KEEP OUT!"
cdf3: "TRAP DOOR!"
cdfe: ", LEVITATION SAVES YOU!"
+movement:
+ obstructed:
+ 0: " SOLID! "
+ 1: " LOCKED! "
+ 2: " TOO DENSE! "
+ 3: " IMPASSABLE "
+ 4: " ROUGH SEAS "
+ 5: " TOO WINDY! "
+view:
+ darkness: " DARKNESS"
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 3a1c69630af..90cbb8c3739 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -40,6 +40,10 @@ enum WallType {
WALL_TORCH = 3
};
+enum CellState {
+ CELL_SPECIAL = 0x80, CELL_DARK = 0x20
+};
+
/**
* The byte structure representing the wall types
* for the four cardinal directions
@@ -56,8 +60,6 @@ private:
Common::String _name;
uint16 _id;
uint _mapId;
- MapWalls _walls[MAP_SIZE];
- byte _states[MAP_SIZE];
Common::Array<byte> _data;
private:
/**
@@ -69,6 +71,9 @@ private:
* Load the map's overlay file
*/
void loadOverlay();
+public:
+ MapWalls _walls[MAP_SIZE];
+ byte _states[MAP_SIZE];
public:
Map(Maps *owner, const Common::String &name, uint16 id);
virtual ~Map() {}
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 1fd1b8e036d..fda1a9db58d 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -78,6 +78,8 @@ Maps::Maps() :
_map48(this), _map49(this), _map50(this), _map51(this),
_map52(this), _map53(this), _map54(this) {
Common::fill(&_data1[0], &_data1[32], 0);
+ _currentWalls._n = _currentWalls._s = WALL_NONE;
+ _currentWalls._e = _currentWalls._w = WALL_NONE;
}
void Maps::load(uint mapId) {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 84ce9349aa5..526823ceddc 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -207,6 +207,8 @@ public:
uint _mapId = (uint)-1;
Common::Point _mapPos;
Map *_currentMap = nullptr;
+ MapWalls _currentWalls;
+ byte _currentState = 0;
byte _data1[32];
int _colorOffset = 0;
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 5dd3c83ad5f..7df4ed7b3ce 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -26,11 +26,156 @@ namespace MM {
namespace MM1 {
namespace Views {
+// TODO: The initial graphics init for EGA divides
+// a bunch of these values by 2
+static byte ARR1[] = { 8, 6, 4, 2 };
+static byte ARR2[] = { 6, 4, 2, 1 };
+static byte ARR3[] = { 4, 5, 3, 2 };
+static byte ARR4[] = { 4, 9, 6, 2 };
+static byte ARR5[] = { 4, 5, 3, 2 };
+static byte ARR6[] = { 22, 12, 6, 2 };
+static byte ARR7[] = { 0, 8, 18, 24 };
+static byte ARR8[] = { 0, 0, 12, 24 };
+static byte ARR9[] = { 52, 42, 36, 32 };
+static byte ARR10[] = { 52, 42, 36, 32 };
+static byte ARR11[] = { 8, 18, 24, 28 };
+static byte ARR12[] = { 8, 10, 6, 4 };
+static byte ARR13[] = { 44, 24, 12, 4 };
+static byte ARR14[] = { 0, 0, 0, 0 };
+static byte ARR15[] = { 36, 4, 0, 0 };
+static byte ARR16[] = { 36, 14, 6, 0 };
+static uint16 ARR17[] = { 0, 0x400, 0x7C0, 0x940 };
+static uint16 ARR18[] = { 0x9C0, 0xDC0, 0x1180, 0x1300 };
+static uint16 ARR19[] = { 0x1380, 0x2400, 0x2A00, 0x2B80 };
+
GameView::GameView() : TextView("View") {
+ Common::fill(&_arr1[0], &_arr1[11], 0);
}
void GameView::draw() {
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *maps._currentMap;
+
+ byte arr1[7];
+ Common::fill(&arr1[0], &arr1[7], 0);
+
+ for (int dist = 0; dist < 4; ++dist,
+ _mapOffset2 += maps._forwardOffset) {
+ byte walls = *((const byte *)&map._walls[_mapOffset2]);
+ byte wallsLeft = *((const byte *)&map._walls[_mapOffset2 + maps._leftOffset]);
+ byte wallsRight = *((const byte *)&map._walls[_mapOffset2 + maps._rightOffset]);
+
+ _mask = walls & maps._leftMask;
+ if (_mask) {
+ _val1 = ARR17[dist];
+ _val2 = ARR3[dist];
+ _val3 = ARR12[dist];
+ _val4 = ARR7[dist];
+ _val5 = ARR1[dist];
+ _val6 = ARR14[dist];
+ arr1[dist * 2 + 1]++;
+ drawTile();
+
+ } else {
+ _mask = wallsLeft & maps._forwardMask;
+ if (_mask) {
+ _val1 = ARR19[dist];
+ arr1[dist * 2 + 1]++;
+
+ if (arr1[dist * 2]) {
+ _val2 = ARR5[dist];
+ _val3 = ARR13[dist];
+ _val4 = ARR7[dist];
+ _val5 = ARR2[dist];
+ _val6 = ARR16[dist];
+ } else {
+ _val2 = ARR4[dist];
+ _val3 = ARR13[dist];
+ _val4 = ARR8[dist];
+ _val5 = ARR2[dist];
+ _val6 = ARR15[dist];
+ }
+
+ drawTile();
+ }
+ }
+
+ _mask = walls & maps._rightMask;
+ if (_mask) {
+ _val1 = ARR18[dist];
+ _val2 = ARR3[dist];
+ _val3 = ARR12[dist];
+ _val4 = ARR9[dist];
+ _val5 = ARR1[dist];
+ _val6 = ARR14[dist];
+ assert(6 + dist * 2 < 11);
+ _arr1[6 + dist * 2]++;
+ drawTile();
+
+ } else {
+ _mask = wallsRight & maps._forwardMask;
+ if (_mask) {
+ _val1 = ARR19[dist];
+ _arr1[6 + dist]++;
+
+ if (_arr1[5 + dist]) {
+ _val2 = ARR5[dist];
+ _val3 = ARR13[dist];
+ _val4 = ARR10[dist];
+ _val5 = ARR2[dist];
+ _val6 = ARR14[dist];
+ } else {
+ _val2 = ARR4[dist];
+ _val3 = ARR13[dist];
+ _val4 = ARR10[dist];
+ _val5 = ARR2[dist];
+ _val6 = ARR14[dist];
+ }
+
+ drawTile();
+ }
+ }
+
+ if (walls & maps._forwardMask) {
+ // Drawing forward blocked by wall
+ _val1 = ARR19[dist];
+ _val2 = ARR6[dist];
+ _val3 = ARR13[dist];
+ _val4 = ARR11[dist];
+ _val5 = ARR2[dist];
+ _val6 = ARR14[dist];
+ drawTile();
+ break;
+ }
+ }
+}
+
+void GameView::drawTile() {
+
+}
+
+void GameView::update() {
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *maps._currentMap;
+ _mapOffset1 = _mapOffset2 = maps._mapPos.y * MAP_W +
+ maps._mapPos.x;
+ maps._currentWalls = map._walls[_mapOffset1];
+ maps._currentState = map._states[_mapOffset1];
+
+ if (maps._currentState & Maps::CELL_DARK) {
+ if (g_globals->_spells._s.light) {
+ g_globals->_spells._s.light--;
+ } else {
+ goto darkness;
+ }
+ }
+
+ if ((map[46] & 1) && !g_globals->_spells._s.light) {
+darkness:
+ // TODO
+ return;
+ }
}
bool GameView::msgAction(const ActionMessage &msg) {
@@ -81,6 +226,10 @@ void GameView::backwards() {
g_globals->_maps.backwards();
}
+void GameView::obstructed() {
+ // TODO
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index df4b4910bf0..075d63081a4 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -29,6 +29,14 @@ namespace MM1 {
namespace Views {
class GameView : public TextView {
+ enum ViewState { VIEW_NORMAL, VIEW_DARKNESS };
+private:
+ int _mapOffset1 = 0, _mapOffset2 = 0;
+ ViewState _state = VIEW_NORMAL;
+ int _val1 = 0, _val2 = 0, _val3 = 0;
+ int _val4 = 0, _val5 = 0, _val6 = 0;
+ byte _mask = 0;
+ byte _arr1[11];
private:
/**
* Turn left
@@ -50,6 +58,15 @@ private:
*/
void backwards();
+ /**
+ * Forward movement is obstructed
+ */
+ void obstructed();
+
+ /**
+ * Draws a tile
+ */
+ void drawTile();
public:
GameView();
virtual ~GameView() {}
@@ -57,6 +74,11 @@ public:
void draw() override;
bool msgGame(const GameMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
+
+ /**
+ * Updates game state
+ */
+ void update();
};
} // namespace Views
Commit: 4b959dd7ae88d8c0b9b3425fa3b5e6749d96ed3b
https://github.com/scummvm/scummvm/commit/4b959dd7ae88d8c0b9b3425fa3b5e6749d96ed3b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: 3d view is starting to render correctly
Changed paths:
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 90cbb8c3739..e0c0882ce36 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -44,17 +44,6 @@ enum CellState {
CELL_SPECIAL = 0x80, CELL_DARK = 0x20
};
-/**
- * The byte structure representing the wall types
- * for the four cardinal directions
- */
-struct MapWalls {
- WallType _n : 2;
- WallType _e : 2;
- WallType _s : 2;
- WallType _w : 2;
-};
-
class Map {
private:
Common::String _name;
@@ -72,7 +61,7 @@ private:
*/
void loadOverlay();
public:
- MapWalls _walls[MAP_SIZE];
+ byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
public:
Map(Maps *owner, const Common::String &name, uint16 id);
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index fda1a9db58d..1fd1b8e036d 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -78,8 +78,6 @@ Maps::Maps() :
_map48(this), _map49(this), _map50(this), _map51(this),
_map52(this), _map53(this), _map54(this) {
Common::fill(&_data1[0], &_data1[32], 0);
- _currentWalls._n = _currentWalls._s = WALL_NONE;
- _currentWalls._e = _currentWalls._w = WALL_NONE;
}
void Maps::load(uint mapId) {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 526823ceddc..b89ea4f6a10 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -207,7 +207,7 @@ public:
uint _mapId = (uint)-1;
Common::Point _mapPos;
Map *_currentMap = nullptr;
- MapWalls _currentWalls;
+ byte _currentWalls = 0;
byte _currentState = 0;
byte _data1[32];
int _colorOffset = 0;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 3e6f7e05a12..81125f25815 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -28,7 +28,8 @@ namespace MM1 {
namespace Views {
Game::Game() : TextView("Game"),
- _commands(this), _messages(this), _party(this) {
+ _view(this), _commands(this),
+ _messages(this), _party(this) {
}
bool Game::msgFocus(const FocusMessage &msg) {
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 7df4ed7b3ce..d288c9939b3 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -44,26 +44,32 @@ static byte ARR13[] = { 44, 24, 12, 4 };
static byte ARR14[] = { 0, 0, 0, 0 };
static byte ARR15[] = { 36, 4, 0, 0 };
static byte ARR16[] = { 36, 14, 6, 0 };
-static uint16 ARR17[] = { 0, 0x400, 0x7C0, 0x940 };
-static uint16 ARR18[] = { 0x9C0, 0xDC0, 0x1180, 0x1300 };
-static uint16 ARR19[] = { 0x1380, 0x2400, 0x2A00, 0x2B80 };
-
-GameView::GameView() : TextView("View") {
+//static uint16 ARR17[] = { 0, 0x400, 0x7C0, 0x940 };
+//static uint16 ARR18[] = { 0x9C0, 0xDC0, 0x1180, 0x1300 };
+//static uint16 ARR19[] = { 0x1380, 0x2400, 0x2A00, 0x2B80 };
+static uint16 ARR17[] = { 0, 1, 2, 3 };
+static uint16 ARR18[] = { 4, 5, 6, 7 };
+static uint16 ARR19[] = { 8, 9, 10, 11 };
+
+GameView::GameView(UIElement *owner) : TextView("View", owner) {
Common::fill(&_arr1[0], &_arr1[11], 0);
}
void GameView::draw() {
+ update(); // TODO: not calling here
+
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
+ int mapOffset = _mapOffset;
byte arr1[7];
Common::fill(&arr1[0], &arr1[7], 0);
for (int dist = 0; dist < 4; ++dist,
- _mapOffset2 += maps._forwardOffset) {
- byte walls = *((const byte *)&map._walls[_mapOffset2]);
- byte wallsLeft = *((const byte *)&map._walls[_mapOffset2 + maps._leftOffset]);
- byte wallsRight = *((const byte *)&map._walls[_mapOffset2 + maps._rightOffset]);
+ mapOffset += maps._forwardOffset) {
+ byte walls = map._walls[mapOffset];
+ byte wallsLeft = map._walls[mapOffset + maps._leftOffset];
+ byte wallsRight = map._walls[mapOffset + maps._rightOffset];
_mask = walls & maps._leftMask;
if (_mask) {
@@ -136,7 +142,8 @@ void GameView::draw() {
}
}
- if (walls & maps._forwardMask) {
+ _mask = walls & maps._forwardMask;
+ if (_mask) {
// Drawing forward blocked by wall
_val1 = ARR19[dist];
_val2 = ARR6[dist];
@@ -147,21 +154,48 @@ void GameView::draw() {
drawTile();
break;
}
+// break; // ****DEBUG*****
}
}
void GameView::drawTile() {
+ Maps::Maps &maps = g_globals->_maps;
+
+ // Determine graphics section to use
+ int section = 0;
+ if ((_mask & 0x55) != _mask) {
+ ++section;
+ if ((_mask & 0xaa) != _mask)
+ ++section;
+ }
+
+ // val1 = src ptr (index in ScummVM)
+ // val6 = src left
+ // val2 = src w
+ // val5 = src h
+ // val3 = src pitch
+ // val4 = dest l?
+
+ Graphics::Screen &scr = *getScreen();
+ const Common::Array<Graphics::ManagedSurface> &tiles =
+ maps._tiles[section];
+ const Graphics::ManagedSurface &tile = tiles[_val1];
+//warning("%x x %x", tile.w, tile.h);
+//warning("%x 0 w: %x, h: %x", _val6, _val2, _val5);
+
+ Common::Point pos(_val4 * 4, (8 - _val5) * 8);
+ Common::Rect r(_val6 * 4, 0, _val6 * 4 + _val2 * 8, tile.h);
+ scr.blitFrom(tile, r, pos);
}
void GameView::update() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
- _mapOffset1 = _mapOffset2 = maps._mapPos.y * MAP_W +
- maps._mapPos.x;
- maps._currentWalls = map._walls[_mapOffset1];
- maps._currentState = map._states[_mapOffset1];
+ _mapOffset = maps._mapPos.y * MAP_W + maps._mapPos.x;
+ maps._currentWalls = map._walls[_mapOffset];
+ maps._currentState = map._states[_mapOffset];
if (maps._currentState & Maps::CELL_DARK) {
if (g_globals->_spells._s.light) {
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index 075d63081a4..aee52941c45 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -31,7 +31,7 @@ namespace Views {
class GameView : public TextView {
enum ViewState { VIEW_NORMAL, VIEW_DARKNESS };
private:
- int _mapOffset1 = 0, _mapOffset2 = 0;
+ int _mapOffset = 0;
ViewState _state = VIEW_NORMAL;
int _val1 = 0, _val2 = 0, _val3 = 0;
int _val4 = 0, _val5 = 0, _val6 = 0;
@@ -68,7 +68,7 @@ private:
*/
void drawTile();
public:
- GameView();
+ GameView(UIElement *owner);
virtual ~GameView() {}
void draw() override;
Commit: 1dd472980c5f3bb6076e0b4beb894e0630c2d034
https://github.com/scummvm/scummvm/commit/1dd472980c5f3bb6076e0b4beb894e0630c2d034
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:47+01:00
Commit Message:
MM: MM1: Split game logic for 3d view into base class
For cleanliness, I want to keep the drawing code
separate from all the code for things like movement.
Changed paths:
A engines/mm/mm1/game/view_base.cpp
A engines/mm/mm1/game/view_base.h
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
new file mode 100644
index 00000000000..4e48c289782
--- /dev/null
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -0,0 +1,109 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/game/view_base.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+ViewBase::ViewBase(UIElement *owner) : Views::TextView("View", owner) {
+}
+
+void ViewBase::update() {
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *maps._currentMap;
+
+ _mapOffset = maps._mapPos.y * MAP_W + maps._mapPos.x;
+ maps._currentWalls = map._walls[_mapOffset];
+ maps._currentState = map._states[_mapOffset];
+
+ if (maps._currentState & Maps::CELL_DARK) {
+ if (g_globals->_spells._s.light) {
+ g_globals->_spells._s.light--;
+ } else {
+ goto darkness;
+ }
+ }
+
+ if ((map[46] & 1) && !g_globals->_spells._s.light) {
+darkness:
+ // TODO
+ return;
+ }
+}
+
+bool ViewBase::msgAction(const ActionMessage &msg) {
+ switch (msg._action) {
+ case KEYBIND_FORWARDS:
+ forward();
+ break;
+ case KEYBIND_BACKWARDS:
+ backwards();
+ break;
+ case KEYBIND_TURN_LEFT:
+ turnLeft();
+ break;
+ case KEYBIND_TURN_RIGHT:
+ turnRight();
+ break;
+ default:
+ return TextView::msgAction(msg);
+ }
+
+ return true;
+}
+
+bool ViewBase::msgGame(const GameMessage &msg) {
+ /*
+ if (msg._name == "DISPLAY") {
+ replaceView(this);
+ return true;
+ }
+ */
+
+ return TextView::msgGame(msg);
+}
+
+void ViewBase::turnLeft() {
+ g_globals->_maps.turnLeft();
+}
+
+void ViewBase::turnRight() {
+ g_globals->_maps.turnRight();
+}
+
+void ViewBase::forward() {
+ g_globals->_maps.forward();
+}
+
+void ViewBase::backwards() {
+ g_globals->_maps.backwards();
+}
+
+void ViewBase::obstructed() {
+ // TODO
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
new file mode 100644
index 00000000000..cbb43120c99
--- /dev/null
+++ b/engines/mm/mm1/game/view_base.h
@@ -0,0 +1,83 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_VIEW_BASE_H
+#define MM1_GAME_VIEW_BASE_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+/**
+ * This acts as the base class for the 3d view
+ * of the surroundings. It contains the all
+ * the gameplay logic except for actual drawing.
+ */
+class ViewBase : public Views::TextView {
+protected:
+ bool _isDark = false;
+ Common::String _message;
+ int _mapOffset = 0;
+private:
+ /**
+ * Turn left
+ */
+ void turnLeft();
+
+ /**
+ * Turn right
+ */
+ void turnRight();
+
+ /**
+ * Move forwards
+ */
+ void forward();
+
+ /**
+ * Move backwards
+ */
+ void backwards();
+
+ /**
+ * Forward movement is obstructed
+ */
+ void obstructed();
+public:
+ ViewBase(UIElement *owner);
+ virtual ~ViewBase() {}
+
+ bool msgGame(const GameMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
+
+ /**
+ * Updates game state
+ */
+ void update();
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index d288c9939b3..9f6e9895533 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -44,14 +44,11 @@ static byte ARR13[] = { 44, 24, 12, 4 };
static byte ARR14[] = { 0, 0, 0, 0 };
static byte ARR15[] = { 36, 4, 0, 0 };
static byte ARR16[] = { 36, 14, 6, 0 };
-//static uint16 ARR17[] = { 0, 0x400, 0x7C0, 0x940 };
-//static uint16 ARR18[] = { 0x9C0, 0xDC0, 0x1180, 0x1300 };
-//static uint16 ARR19[] = { 0x1380, 0x2400, 0x2A00, 0x2B80 };
static uint16 ARR17[] = { 0, 1, 2, 3 };
static uint16 ARR18[] = { 4, 5, 6, 7 };
static uint16 ARR19[] = { 8, 9, 10, 11 };
-GameView::GameView(UIElement *owner) : TextView("View", owner) {
+GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
Common::fill(&_arr1[0], &_arr1[11], 0);
}
@@ -65,12 +62,14 @@ void GameView::draw() {
byte arr1[7];
Common::fill(&arr1[0], &arr1[7], 0);
+ // Loop through four regions in front of the party
for (int dist = 0; dist < 4; ++dist,
mapOffset += maps._forwardOffset) {
byte walls = map._walls[mapOffset];
byte wallsLeft = map._walls[mapOffset + maps._leftOffset];
byte wallsRight = map._walls[mapOffset + maps._rightOffset];
+ // Draw left-hand side
_mask = walls & maps._leftMask;
if (_mask) {
_val1 = ARR17[dist];
@@ -106,6 +105,7 @@ void GameView::draw() {
}
}
+ // Draw right-hand side
_mask = walls & maps._rightMask;
if (_mask) {
_val1 = ARR18[dist];
@@ -142,9 +142,9 @@ void GameView::draw() {
}
}
+ // Handle drawing any wall directly in front
_mask = walls & maps._forwardMask;
if (_mask) {
- // Drawing forward blocked by wall
_val1 = ARR19[dist];
_val2 = ARR6[dist];
_val3 = ARR13[dist];
@@ -154,7 +154,6 @@ void GameView::draw() {
drawTile();
break;
}
-// break; // ****DEBUG*****
}
}
@@ -169,19 +168,10 @@ void GameView::drawTile() {
++section;
}
- // val1 = src ptr (index in ScummVM)
- // val6 = src left
- // val2 = src w
- // val5 = src h
- // val3 = src pitch
- // val4 = dest l?
-
Graphics::Screen &scr = *getScreen();
const Common::Array<Graphics::ManagedSurface> &tiles =
maps._tiles[section];
const Graphics::ManagedSurface &tile = tiles[_val1];
-//warning("%x x %x", tile.w, tile.h);
-//warning("%x 0 w: %x, h: %x", _val6, _val2, _val5);
Common::Point pos(_val4 * 4, (8 - _val5) * 8);
Common::Rect r(_val6 * 4, 0, _val6 * 4 + _val2 * 8, tile.h);
@@ -189,81 +179,6 @@ void GameView::drawTile() {
scr.blitFrom(tile, r, pos);
}
-void GameView::update() {
- Maps::Maps &maps = g_globals->_maps;
- Maps::Map &map = *maps._currentMap;
-
- _mapOffset = maps._mapPos.y * MAP_W + maps._mapPos.x;
- maps._currentWalls = map._walls[_mapOffset];
- maps._currentState = map._states[_mapOffset];
-
- if (maps._currentState & Maps::CELL_DARK) {
- if (g_globals->_spells._s.light) {
- g_globals->_spells._s.light--;
- } else {
- goto darkness;
- }
- }
-
- if ((map[46] & 1) && !g_globals->_spells._s.light) {
-darkness:
- // TODO
- return;
- }
-}
-
-bool GameView::msgAction(const ActionMessage &msg) {
- switch (msg._action) {
- case KEYBIND_FORWARDS:
- forward();
- break;
- case KEYBIND_BACKWARDS:
- backwards();
- break;
- case KEYBIND_TURN_LEFT:
- turnLeft();
- break;
- case KEYBIND_TURN_RIGHT:
- turnRight();
- break;
- default:
- return TextView::msgAction(msg);
- }
-
- return true;
-}
-
-bool GameView::msgGame(const GameMessage &msg) {
- /*
- if (msg._name == "DISPLAY") {
- replaceView(this);
- return true;
- }
- */
-
- return TextView::msgGame(msg);
-}
-
-void GameView::turnLeft() {
- g_globals->_maps.turnLeft();
-}
-
-void GameView::turnRight() {
- g_globals->_maps.turnRight();
-}
-
-void GameView::forward() {
- g_globals->_maps.forward();
-}
-
-void GameView::backwards() {
- g_globals->_maps.backwards();
-}
-
-void GameView::obstructed() {
- // TODO
-}
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index aee52941c45..97bce8bd0d7 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -22,47 +22,19 @@
#ifndef MM1_VIEWS_GAME_VIEW_H
#define MM1_VIEWS_GAME_VIEW_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/game/view_base.h"
namespace MM {
namespace MM1 {
namespace Views {
-class GameView : public TextView {
- enum ViewState { VIEW_NORMAL, VIEW_DARKNESS };
+class GameView : public Game::ViewBase {
private:
- int _mapOffset = 0;
- ViewState _state = VIEW_NORMAL;
int _val1 = 0, _val2 = 0, _val3 = 0;
int _val4 = 0, _val5 = 0, _val6 = 0;
byte _mask = 0;
byte _arr1[11];
private:
- /**
- * Turn left
- */
- void turnLeft();
-
- /**
- * Turn right
- */
- void turnRight();
-
- /**
- * Move forwards
- */
- void forward();
-
- /**
- * Move backwards
- */
- void backwards();
-
- /**
- * Forward movement is obstructed
- */
- void obstructed();
-
/**
* Draws a tile
*/
@@ -72,13 +44,6 @@ public:
virtual ~GameView() {}
void draw() override;
- bool msgGame(const GameMessage &msg) override;
- bool msgAction(const ActionMessage &msg) override;
-
- /**
- * Updates game state
- */
- void update();
};
} // namespace Views
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c26579a19fd..b136e2f8670 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS := \
mm1/data/char.o \
mm1/data/game_state.o \
mm1/data/roster.o \
+ mm1/game/view_base.o \
mm1/gfx/dta.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
Commit: f15dd4618afe0767dd97cf9def7bcf00a3853ac8
https://github.com/scummvm/scummvm/commit/f15dd4618afe0767dd97cf9def7bcf00a3853ac8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:48+01:00
Commit Message:
MM: MM1: Turning left and right re-renders view
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 76e1b9f38c6..223d9b12aae 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -145,10 +145,10 @@ void UIElement::drawElements() {
if (_needsRedraw) {
draw();
_needsRedraw = false;
-
- for (size_t i = 0; i < _children.size(); ++i)
- _children[i]->drawElements();
}
+
+ for (size_t i = 0; i < _children.size(); ++i)
+ _children[i]->drawElements();
}
void UIElement::focus() {
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 4e48c289782..0441877e511 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -36,6 +36,7 @@ void ViewBase::update() {
_mapOffset = maps._mapPos.y * MAP_W + maps._mapPos.x;
maps._currentWalls = map._walls[_mapOffset];
maps._currentState = map._states[_mapOffset];
+ _isDark = false;
if (maps._currentState & Maps::CELL_DARK) {
if (g_globals->_spells._s.light) {
@@ -48,8 +49,11 @@ void ViewBase::update() {
if ((map[46] & 1) && !g_globals->_spells._s.light) {
darkness:
// TODO
- return;
+ _isDark = true;
}
+
+ // Redraw the screen
+ redraw();
}
bool ViewBase::msgAction(const ActionMessage &msg) {
@@ -73,6 +77,11 @@ bool ViewBase::msgAction(const ActionMessage &msg) {
return true;
}
+bool ViewBase::msgFocus(const FocusMessage &msg) {
+ update();
+ return false;
+}
+
bool ViewBase::msgGame(const GameMessage &msg) {
/*
if (msg._name == "DISPLAY") {
@@ -86,18 +95,22 @@ bool ViewBase::msgGame(const GameMessage &msg) {
void ViewBase::turnLeft() {
g_globals->_maps.turnLeft();
+ update();
}
void ViewBase::turnRight() {
g_globals->_maps.turnRight();
+ update();
}
void ViewBase::forward() {
g_globals->_maps.forward();
+ update();
}
void ViewBase::backwards() {
g_globals->_maps.backwards();
+ update();
}
void ViewBase::obstructed() {
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index cbb43120c99..5672e342008 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -67,6 +67,7 @@ public:
ViewBase(UIElement *owner);
virtual ~ViewBase() {}
+ bool msgFocus(const FocusMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 81125f25815..fe7552ada8a 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -34,7 +34,7 @@ Game::Game() : TextView("Game"),
bool Game::msgFocus(const FocusMessage &msg) {
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_NORMAL);
- return true;
+ return TextView::msgFocus(msg);
}
bool Game::msgUnfocus(const UnfocusMessage &msg) {
@@ -43,9 +43,8 @@ bool Game::msgUnfocus(const UnfocusMessage &msg) {
}
void Game::draw() {
- // Clear the screen, and then call superclass
- // to render the subviews within the view
- clearScreen();
+ if (_needsRedraw)
+ clearScreen();
UIElement::draw();
}
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 9f6e9895533..759a04206ee 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -26,8 +26,6 @@ namespace MM {
namespace MM1 {
namespace Views {
-// TODO: The initial graphics init for EGA divides
-// a bunch of these values by 2
static byte ARR1[] = { 8, 6, 4, 2 };
static byte ARR2[] = { 6, 4, 2, 1 };
static byte ARR3[] = { 4, 5, 3, 2 };
@@ -53,8 +51,6 @@ GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
}
void GameView::draw() {
- update(); // TODO: not calling here
-
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
int mapOffset = _mapOffset;
@@ -62,6 +58,8 @@ void GameView::draw() {
byte arr1[7];
Common::fill(&arr1[0], &arr1[7], 0);
+ getScreen()->fillRect(Common::Rect(0, 0, 245, 128), 0);
+
// Loop through four regions in front of the party
for (int dist = 0; dist < 4; ++dist,
mapOffset += maps._forwardOffset) {
@@ -72,33 +70,33 @@ void GameView::draw() {
// Draw left-hand side
_mask = walls & maps._leftMask;
if (_mask) {
- _val1 = ARR17[dist];
- _val2 = ARR3[dist];
- _val3 = ARR12[dist];
- _val4 = ARR7[dist];
- _val5 = ARR1[dist];
- _val6 = ARR14[dist];
+ _tileIndex = ARR17[dist];
+ _srcWidth = ARR3[dist];
+ _srcPitch = ARR12[dist];
+ _destLeft = ARR7[dist];
+ _destTop = ARR1[dist];
+ _srcLeft = ARR14[dist];
arr1[dist * 2 + 1]++;
drawTile();
} else {
_mask = wallsLeft & maps._forwardMask;
if (_mask) {
- _val1 = ARR19[dist];
+ _tileIndex = ARR19[dist];
arr1[dist * 2 + 1]++;
if (arr1[dist * 2]) {
- _val2 = ARR5[dist];
- _val3 = ARR13[dist];
- _val4 = ARR7[dist];
- _val5 = ARR2[dist];
- _val6 = ARR16[dist];
+ _srcWidth = ARR5[dist];
+ _srcPitch = ARR13[dist];
+ _destLeft = ARR7[dist];
+ _destTop = ARR2[dist];
+ _srcLeft = ARR16[dist];
} else {
- _val2 = ARR4[dist];
- _val3 = ARR13[dist];
- _val4 = ARR8[dist];
- _val5 = ARR2[dist];
- _val6 = ARR15[dist];
+ _srcWidth = ARR4[dist];
+ _srcPitch = ARR13[dist];
+ _destLeft = ARR8[dist];
+ _destTop = ARR2[dist];
+ _srcLeft = ARR15[dist];
}
drawTile();
@@ -108,12 +106,12 @@ void GameView::draw() {
// Draw right-hand side
_mask = walls & maps._rightMask;
if (_mask) {
- _val1 = ARR18[dist];
- _val2 = ARR3[dist];
- _val3 = ARR12[dist];
- _val4 = ARR9[dist];
- _val5 = ARR1[dist];
- _val6 = ARR14[dist];
+ _tileIndex = ARR18[dist];
+ _srcWidth = ARR3[dist];
+ _srcPitch = ARR12[dist];
+ _destLeft = ARR9[dist];
+ _destTop = ARR1[dist];
+ _srcLeft = ARR14[dist];
assert(6 + dist * 2 < 11);
_arr1[6 + dist * 2]++;
drawTile();
@@ -121,21 +119,21 @@ void GameView::draw() {
} else {
_mask = wallsRight & maps._forwardMask;
if (_mask) {
- _val1 = ARR19[dist];
+ _tileIndex = ARR19[dist];
_arr1[6 + dist]++;
if (_arr1[5 + dist]) {
- _val2 = ARR5[dist];
- _val3 = ARR13[dist];
- _val4 = ARR10[dist];
- _val5 = ARR2[dist];
- _val6 = ARR14[dist];
+ _srcWidth = ARR5[dist];
+ _srcPitch = ARR13[dist];
+ _destLeft = ARR10[dist];
+ _destTop = ARR2[dist];
+ _srcLeft = ARR14[dist];
} else {
- _val2 = ARR4[dist];
- _val3 = ARR13[dist];
- _val4 = ARR10[dist];
- _val5 = ARR2[dist];
- _val6 = ARR14[dist];
+ _srcWidth = ARR4[dist];
+ _srcPitch = ARR13[dist];
+ _destLeft = ARR10[dist];
+ _destTop = ARR2[dist];
+ _srcLeft = ARR14[dist];
}
drawTile();
@@ -145,12 +143,12 @@ void GameView::draw() {
// Handle drawing any wall directly in front
_mask = walls & maps._forwardMask;
if (_mask) {
- _val1 = ARR19[dist];
- _val2 = ARR6[dist];
- _val3 = ARR13[dist];
- _val4 = ARR11[dist];
- _val5 = ARR2[dist];
- _val6 = ARR14[dist];
+ _tileIndex = ARR19[dist];
+ _srcWidth = ARR6[dist];
+ _srcPitch = ARR13[dist];
+ _destLeft = ARR11[dist];
+ _destTop = ARR2[dist];
+ _srcLeft = ARR14[dist];
drawTile();
break;
}
@@ -171,10 +169,10 @@ void GameView::drawTile() {
Graphics::Screen &scr = *getScreen();
const Common::Array<Graphics::ManagedSurface> &tiles =
maps._tiles[section];
- const Graphics::ManagedSurface &tile = tiles[_val1];
+ const Graphics::ManagedSurface &tile = tiles[_tileIndex];
- Common::Point pos(_val4 * 4, (8 - _val5) * 8);
- Common::Rect r(_val6 * 4, 0, _val6 * 4 + _val2 * 8, tile.h);
+ Common::Point pos(_destLeft * 4, (8 - _destTop) * 8);
+ Common::Rect r(_srcLeft * 4, 0, _srcLeft * 4 + _srcWidth * 8, tile.h);
scr.blitFrom(tile, r, pos);
}
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index 97bce8bd0d7..2c038311620 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -30,8 +30,8 @@ namespace Views {
class GameView : public Game::ViewBase {
private:
- int _val1 = 0, _val2 = 0, _val3 = 0;
- int _val4 = 0, _val5 = 0, _val6 = 0;
+ int _tileIndex = 0, _srcWidth = 0, _srcPitch = 0;
+ int _destLeft = 0, _destTop = 0, _srcLeft = 0;
byte _mask = 0;
byte _arr1[11];
private:
Commit: 96d1a1de39f210d79d19ede348fb896f4a1dfce6
https://github.com/scummvm/scummvm/commit/96d1a1de39f210d79d19ede348fb896f4a1dfce6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:48+01:00
Commit Message:
MM: MM1: Dummy implementation for forward/backwards
Changed paths:
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 1fd1b8e036d..ff4f1f24f22 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -264,11 +264,45 @@ void Maps::turnRight() {
}
void Maps::forward() {
-
+ // TODO: Properly implement this for
+ // checking for obstructions and map changes
+ switch (_forwardMask) {
+ case DIRMASK_N:
+ _mapPos.y++;
+ break;
+ case DIRMASK_S:
+ _mapPos.y--;
+ break;
+ case DIRMASK_E:
+ _mapPos.x++;
+ break;
+ case DIRMASK_W:
+ _mapPos.x--;
+ break;
+ default:
+ break;
+ }
}
void Maps::backwards() {
-
+ // TODO: Properly implement this for
+ // checking for obstructions and map changes
+ switch (_forwardMask) {
+ case DIRMASK_N:
+ _mapPos.y--;
+ break;
+ case DIRMASK_S:
+ _mapPos.y++;
+ break;
+ case DIRMASK_E:
+ _mapPos.x--;
+ break;
+ case DIRMASK_W:
+ _mapPos.x++;
+ break;
+ default:
+ break;
+ }
}
} // namespace Maps
Commit: a8b5ed0e7da7f7761b76fcaad98886bb2ff624ac
https://github.com/scummvm/scummvm/commit/a8b5ed0e7da7f7761b76fcaad98886bb2ff624ac
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:48+01:00
Commit Message:
MM: MM1: Fixes to 3d wall rendering
Changed paths:
engines/mm/mm1/views/game_view.cpp
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 759a04206ee..d1343e805b6 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -55,8 +55,7 @@ void GameView::draw() {
Maps::Map &map = *maps._currentMap;
int mapOffset = _mapOffset;
- byte arr1[7];
- Common::fill(&arr1[0], &arr1[7], 0);
+ Common::fill(&_arr1[0], &_arr1[11], 0);
getScreen()->fillRect(Common::Rect(0, 0, 245, 128), 0);
@@ -76,16 +75,16 @@ void GameView::draw() {
_destLeft = ARR7[dist];
_destTop = ARR1[dist];
_srcLeft = ARR14[dist];
- arr1[dist * 2 + 1]++;
+ _arr1[dist + 1]++;
drawTile();
} else {
_mask = wallsLeft & maps._forwardMask;
if (_mask) {
_tileIndex = ARR19[dist];
- arr1[dist * 2 + 1]++;
+ _arr1[dist + 1]++;
- if (arr1[dist * 2]) {
+ if (_arr1[dist]) {
_srcWidth = ARR5[dist];
_srcPitch = ARR13[dist];
_destLeft = ARR7[dist];
@@ -112,8 +111,7 @@ void GameView::draw() {
_destLeft = ARR9[dist];
_destTop = ARR1[dist];
_srcLeft = ARR14[dist];
- assert(6 + dist * 2 < 11);
- _arr1[6 + dist * 2]++;
+ _arr1[dist + 1]++;
drawTile();
} else {
Commit: 5012806724ec84250937e2d60a44e753c2ccb07f
https://github.com/scummvm/scummvm/commit/5012806724ec84250937e2d60a44e753c2ccb07f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:48+01:00
Commit Message:
MM: MM1: Implement support for element bounds
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/protect.cpp
engines/mm/mm1/views/quick_ref.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/mm1/views/title.cpp
engines/mm/mm1/views/view_characters.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 223d9b12aae..0ec7a12ae2c 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -23,6 +23,7 @@
#include "graphics/screen.h"
#include "mm/mm1/events.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/gfx/gfx.h"
#include "mm/mm1/views/dialogs.h"
namespace MM {
@@ -129,7 +130,8 @@ void Events::popView() {
/*------------------------------------------------------------------------*/
UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
- _name(name), _parent(uiParent) {
+ _name(name), _parent(uiParent),
+ _bounds(0, 0, SCREEN_W, SCREEN_H) {
if (_parent)
_parent->_children.push_back(this);
}
@@ -208,5 +210,13 @@ void UIElement::addView() {
g_events->addView(this);
}
+Graphics::Surface UIElement::getSurface() const {
+ if (_bounds.width() == SCREEN_W &&
+ _bounds.height() == SCREEN_H)
+ return *g_events->getScreen();
+ else
+ return g_events->getScreen()->getSubArea(_bounds);
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 4b07b0ef9a1..e8bb9a36e10 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -61,6 +61,7 @@ class UIElement {
protected:
UIElement *_parent;
Common::Array<UIElement *> _children;
+ Common::Rect _bounds;
bool _needsRedraw = true;
Common::String _name;
private:
@@ -108,11 +109,9 @@ public:
void addView();
/**
- * Returns the game view
+ * Returns a surface for drawing the element
*/
- virtual Graphics::Screen *getScreen() const {
- return _parent ? _parent->getScreen() : nullptr;
- }
+ Graphics::Surface getSurface() const;
/**
* Draws the element
@@ -191,7 +190,7 @@ public:
return _views.empty() ? nullptr : _views.top();
}
- Graphics::Screen *getScreen() const override {
+ Graphics::Screen *getScreen() const {
return _screen;
}
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index fe7552ada8a..13bafe415b8 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -44,7 +44,7 @@ bool Game::msgUnfocus(const UnfocusMessage &msg) {
void Game::draw() {
if (_needsRedraw)
- clearScreen();
+ clearSurface();
UIElement::draw();
}
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index d1343e805b6..452024d8638 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -47,6 +47,7 @@ static uint16 ARR18[] = { 4, 5, 6, 7 };
static uint16 ARR19[] = { 8, 9, 10, 11 };
GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
+ _bounds = Common::Rect(0, 0, 245, 128);
Common::fill(&_arr1[0], &_arr1[11], 0);
}
@@ -57,7 +58,7 @@ void GameView::draw() {
Common::fill(&_arr1[0], &_arr1[11], 0);
- getScreen()->fillRect(Common::Rect(0, 0, 245, 128), 0);
+ clearSurface();
// Loop through four regions in front of the party
for (int dist = 0; dist < 4; ++dist,
@@ -164,7 +165,7 @@ void GameView::drawTile() {
++section;
}
- Graphics::Screen &scr = *getScreen();
+ Graphics::Surface surf = getSurface();
const Common::Array<Graphics::ManagedSurface> &tiles =
maps._tiles[section];
const Graphics::ManagedSurface &tile = tiles[_tileIndex];
@@ -172,7 +173,7 @@ void GameView::drawTile() {
Common::Point pos(_destLeft * 4, (8 - _destTop) * 8);
Common::Rect r(_srcLeft * 4, 0, _srcLeft * 4 + _srcWidth * 8, tile.h);
- scr.blitFrom(tile, r, pos);
+ surf.copyRectToSurface(tile, pos.x, pos.y, r);
}
} // namespace Views
diff --git a/engines/mm/mm1/views/protect.cpp b/engines/mm/mm1/views/protect.cpp
index 45c92be7133..de2afc1b51f 100644
--- a/engines/mm/mm1/views/protect.cpp
+++ b/engines/mm/mm1/views/protect.cpp
@@ -27,7 +27,7 @@ namespace MM1 {
namespace Views {
void Protect::draw() {
- clearScreen();
+ clearSurface();
writeString(STRING["dialogs.protect.title"]);
escToGoBack();
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 7dfe5d4033e..34cda7d3738 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -27,7 +27,7 @@ namespace MM1 {
namespace Views {
void QuickRef::draw() {
- clearScreen();
+ clearSurface();
writeString(STRING["dialogs.quick_ref.title"]);
// Print list of characters, hit pts, spell pts, and ac
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 97e8ff960e3..f06630960a2 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -37,7 +37,8 @@ TextView::TextView(const Common::String &name, UIElement *owner) :
}
void TextView::writeChar(char c) {
- g_globals->_font->drawChar(getScreen(), c,
+ Graphics::Surface s = getSurface();
+ g_globals->_font->drawChar(&s, c,
_textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
if (++_textPos.x == TEXT_W) {
@@ -78,22 +79,23 @@ void TextView::newLine() {
_textPos.y++;
}
-void TextView::clearScreen() {
- getScreen()->clear();
+void TextView::clearSurface() {
+ Graphics::Surface s = getSurface();
+ s.fillRect(Common::Rect(s.w, s.h), 0);
_textPos.x = _textPos.y = 0;
}
void TextView::drawTextBorder() {
- Graphics::ManagedSurface *scr = getScreen();
- clearScreen();
+ Graphics::Surface surf = getSurface();
+ clearSurface();
// Draw boxes in the four corners
- scr->fillRect(Common::Rect(0, 0, FONT_SIZE * 3, FONT_SIZE * 3), 255);
- scr->fillRect(Common::Rect(SCREEN_W - FONT_SIZE * 3, 0,
+ surf.fillRect(Common::Rect(0, 0, FONT_SIZE * 3, FONT_SIZE * 3), 255);
+ surf.fillRect(Common::Rect(SCREEN_W - FONT_SIZE * 3, 0,
SCREEN_W, FONT_SIZE * 3), 255);
- scr->fillRect(Common::Rect(0, SCREEN_H - FONT_SIZE * 3,
+ surf.fillRect(Common::Rect(0, SCREEN_H - FONT_SIZE * 3,
FONT_SIZE * 3, SCREEN_H), 255);
- scr->fillRect(Common::Rect(SCREEN_W - FONT_SIZE * 3,
+ surf.fillRect(Common::Rect(SCREEN_W - FONT_SIZE * 3,
SCREEN_H - FONT_SIZE * 3, SCREEN_W, SCREEN_H), 255);
// Draw horizontal vertical lines
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 6685591121d..98310e69b3e 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -60,9 +60,9 @@ protected:
void newLine();
/**
- * Clear the screen
+ * Clear the surface
*/
- void clearScreen();
+ void clearSurface();
/**
* Draws a text border
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index 2383e08aa97..ed5f6470704 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views/title.h"
+#include "mm/mm1/gfx/gfx.h"
#include "mm/mm1/gfx/screen_decoder.h"
#include "mm/mm1/mm1.h"
@@ -37,7 +38,7 @@ Title::Title() : UIElement("Title", g_engine) {
}
void Title::draw() {
- getScreen()->blitFrom(_surface);
+ getSurface().copyFrom(_surface);
}
} // namespace Views
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index 057b912d05f..fbc3d0bb5b3 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -256,7 +256,7 @@ void CharacterStats::printInventory() {
void ViewCharacter::draw() {
assert(g_globals->_currCharacter);
- clearScreen();
+ clearSurface();
printStats();
switch (_state) {
Commit: ffef7976f2a394c2309c3280c3da64fd39e5807b
https://github.com/scummvm/scummvm/commit/ffef7976f2a394c2309c3280c3da64fd39e5807b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:48+01:00
Commit Message:
MM: MM1: Beginnings of enhanced mode
Changed paths:
A engines/mm/mm1/views_enh/dialogs.cpp
A engines/mm/mm1/views_enh/dialogs.h
A engines/mm/mm1/views_enh/game.cpp
A engines/mm/mm1/views_enh/game.h
engines/mm/detection.cpp
engines/mm/detection.h
engines/mm/detection_tables.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/mm1.cpp
engines/mm/module.mk
diff --git a/engines/mm/detection.cpp b/engines/mm/detection.cpp
index 856fd253f1e..e87b2db6d15 100644
--- a/engines/mm/detection.cpp
+++ b/engines/mm/detection.cpp
@@ -27,6 +27,7 @@
static const PlainGameDescriptor MIGHT_AND_MAGIC_GAMES[] = {
{ "mm1", "Might and Magic: Book One - Secret of the Inner Sanctum"},
+ { "mm1_enh", "Might and Magic: Book One - Secret of the Inner Sanctum - Enhanced"},
{ "cloudsofxeen", "Might and Magic IV: Clouds of Xeen" },
{ "darksideofxeen", "Might and Magic V: Darkside of Xeen" },
{ "worldofxeen", "Might and Magic: World of Xeen" },
diff --git a/engines/mm/detection.h b/engines/mm/detection.h
index 05a7cfcff1b..f5ddda500e2 100644
--- a/engines/mm/detection.h
+++ b/engines/mm/detection.h
@@ -34,6 +34,11 @@ enum {
GType_Swords
};
+enum GameFeature {
+ GF_NONE = 0,
+ GF_ENHANCED = 1
+};
+
struct MightAndMagicGameDescription {
ADGameDescription desc;
diff --git a/engines/mm/detection_tables.h b/engines/mm/detection_tables.h
index 43192b4c28e..f97f2542999 100644
--- a/engines/mm/detection_tables.h
+++ b/engines/mm/detection_tables.h
@@ -37,6 +37,20 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
0
},
+ {
+ // Might and Magic 1 (Enhanced)
+ {
+ "mm1_enh",
+ nullptr,
+ AD_ENTRY1s("wallpix.dta", "86a7ef03fd5bf434d83012b07fa92680", 123059),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ GType_MightAndMagic1,
+ GF_ENHANCED
+ },
{
// World of Xeen
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 0ec7a12ae2c..f2cd2a30757 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -25,6 +25,7 @@
#include "mm/mm1/mm1.h"
#include "mm/mm1/gfx/gfx.h"
#include "mm/mm1/views/dialogs.h"
+#include "mm/mm1/views_enh/dialogs.h"
namespace MM {
namespace MM1 {
@@ -34,7 +35,8 @@ namespace MM1 {
Events *g_events;
-Events::Events() : UIElement("", nullptr) {
+Events::Events(bool enhancedMode) : UIElement("", nullptr),
+ _enhancedMode(enhancedMode) {
g_events = this;
}
@@ -43,8 +45,9 @@ Events::~Events() {
}
void Events::runGame() {
- Views::Dialogs dialogsContainer; // Load up all the dialogs
-
+ UIElement *allViews = _enhancedMode ?
+ (UIElement *)new ViewsEnh::Dialogs() :
+ (UIElement *)new Views::Dialogs();
uint currTime, nextFrameTime = 0;
_screen = new Graphics::Screen();
@@ -71,6 +74,7 @@ void Events::runGame() {
}
delete _screen;
+ delete allViews;
}
void Events::processEvent(Common::Event &ev) {
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index e8bb9a36e10..a10e9365e22 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -152,13 +152,14 @@ class Events : public UIElement {
private:
Graphics::Screen *_screen = nullptr;
Common::Stack<UIElement *> _views;
+ bool _enhancedMode;
protected:
/**
* Process an event
*/
void processEvent(Common::Event &ev);
public:
- Events();
+ Events(bool enhancedMode);
virtual ~Events();
/**
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 7f466a12aaa..c90d75b6cce 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -34,7 +34,8 @@ namespace MM1 {
MM1Engine *g_engine = nullptr;
MM1Engine::MM1Engine(OSystem *syst, const MightAndMagicGameDescription *gameDesc)
- : Engine(syst), _gameDescription(gameDesc), _randomSource("MM1") {
+ : Engine(syst), Events(gameDesc->features & GF_ENHANCED),
+ _gameDescription(gameDesc), _randomSource("MM1") {
g_engine = this;
}
diff --git a/engines/mm/mm1/views_enh/dialogs.cpp b/engines/mm/mm1/views_enh/dialogs.cpp
new file mode 100644
index 00000000000..a7e89d74b9a
--- /dev/null
+++ b/engines/mm/mm1/views_enh/dialogs.cpp
@@ -0,0 +1,31 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/dialogs.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
new file mode 100644
index 00000000000..0ab12680c3e
--- /dev/null
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_DIALOGS_H
+#define MM1_VIEWS_ENH_DIALOGS_H
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/views/are_you_ready.h"
+#include "mm/mm1/views/create_characters.h"
+#include "mm/mm1/views/inn.h"
+#include "mm/mm1/views/main_menu.h"
+#include "mm/mm1/views/protect.h"
+#include "mm/mm1/views/quick_ref.h"
+#include "mm/mm1/views/title.h"
+#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/views_enh/game.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+struct Dialogs {
+private:
+ ViewsEnh::Game _game;
+
+ // Unenhanced views
+ Views::AreYouReady _areYouReady;
+ Views::CreateCharacters _createCharacters;
+ Views::Inn _inn;
+ Views::MainMenu _mainMenu;
+ Views::Protect _protect;
+ Views::QuickRef _quickRef;
+ Views::Title _title;
+ Views::ViewCharacters _viewCharacters;
+ Views::ViewCharacter _viewCharacter;
+public:
+ Dialogs() {}
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
new file mode 100644
index 00000000000..58357a5a110
--- /dev/null
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/game.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/meta_engine.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+Game::Game() : TextView("Game"),
+ _view(this) {
+}
+
+bool Game::msgFocus(const FocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_NORMAL);
+ return TextView::msgFocus(msg);
+}
+
+bool Game::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return true;
+}
+
+void Game::draw() {
+ if (_needsRedraw)
+ clearSurface();
+ UIElement::draw();
+}
+
+bool Game::msgKeypress(const KeypressMessage &msg) {
+ return true;
+}
+
+bool Game::msgGame(const GameMessage &msg) {
+ if (msg._name == "DISPLAY") {
+ replaceView(this);
+ return true;
+ }
+
+ return TextView::msgGame(msg);
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/game.h b/engines/mm/mm1/views_enh/game.h
new file mode 100644
index 00000000000..6e48b450847
--- /dev/null
+++ b/engines/mm/mm1/views_enh/game.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_GAME_H
+#define MM1_VIEWS_ENH_GAME_H
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/views/game_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class Game : public Views::TextView {
+private:
+ Views::GameView _view;
+public:
+ Game();
+ virtual ~Game() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgGame(const GameMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b136e2f8670..aadabca877a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -31,6 +31,8 @@ MODULE_OBJS := \
mm1/views/title.o \
mm1/views/text_view.o \
mm1/views/view_characters.o \
+ mm1/views_enh/dialogs.o \
+ mm1/views_enh/game.o \
mm1/maps/maps.o \
mm1/maps/map.o \
mm1/maps/map00.o \
Commit: 5f79a8b266cfb1f6c3b052a6431600511e862698
https://github.com/scummvm/scummvm/commit/5f79a8b266cfb1f6c3b052a6431600511e862698
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:48+01:00
Commit Message:
MM: MM1: Load Xeen UI background
Changed paths:
engines/mm/mm1/mm1.cpp
engines/mm/mm1/mm1.h
engines/mm/mm1/views_enh/game.cpp
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index c90d75b6cce..fd931234dbd 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -22,11 +22,14 @@
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
-#include "common/events.h"
+#include "common/file.h"
+#include "common/system.h"
#include "engines/util.h"
+#include "graphics/palette.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/console.h"
#include "mm/mm1/gfx/gfx.h"
+#include "mm/xeen/files.h"
namespace MM {
namespace MM1 {
@@ -46,8 +49,15 @@ MM1Engine::~MM1Engine() {
Common::Error MM1Engine::run() {
// Initialize graphics mode
initGraphics(320, 200);
- Gfx::GFX::setEgaPalette(0);
+ if (isEnhanced()) {
+ if (!setupEnhanced())
+ return Common::kNoError;
+ } else {
+ setupNormal();
+ }
+
+ // Setup console
setDebugger(new Console());
// Load globals
@@ -58,5 +68,42 @@ Common::Error MM1Engine::run() {
return Common::kNoError;
}
+bool MM1Engine::isEnhanced() const {
+ return (_gameDescription->features & GF_ENHANCED) != 0;
+}
+
+void MM1Engine::setupNormal() {
+ Gfx::GFX::setEgaPalette(0);
+}
+
+bool MM1Engine::setupEnhanced() {
+ if (!Common::File::exists("dark.cc")) {
+ GUIErrorMessage(
+ "In order to run in Enhanced mode, please copy dark.cc "
+ "from a copy of World of Xeen\n"
+ "or Dark Side of Xeen to your Might and Magic 1 game folder"
+ );
+
+ return false;
+ }
+
+ // Add the Dark Side dark.cc archive
+ ::MM::Xeen::CCArchive *darkCC = new ::MM::Xeen::CCArchive(
+ "dark.cc", "dark", true);
+ SearchMan.add("dark", darkCC);
+
+ // Load the palette
+ Common::File f;
+ if (!f.open("dark.pal"))
+ error("Could not load palette");
+
+ byte pal[PALETTE_SIZE];
+ for (int i = 0; i < PALETTE_SIZE; ++i)
+ pal[i] = f.readByte() << 2;
+ g_system->getPaletteManager()->setPalette(pal, 0, PALETTE_COUNT);
+
+ return true;
+}
+
} // End of namespace Xeen
} // End of namespace MM
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index 1dce4bd2138..2d1f2dd8d77 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -42,6 +42,9 @@ private:
// Engine APIs
Common::Error run() override;
+ bool isEnhanced() const;
+ void setupNormal();
+ bool setupEnhanced();
public:
Globals _globals;
public:
@@ -57,6 +60,7 @@ public:
int getRandomNumber(int maxNumber) {
return _randomSource.getRandomNumber(maxNumber);
}
+
Common::String getTargetName() const {
return _targetName;
}
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index 58357a5a110..4589ee6b694 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/file.h"
#include "mm/mm1/views_enh/game.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/meta_engine.h"
@@ -42,8 +43,16 @@ bool Game::msgUnfocus(const UnfocusMessage &msg) {
}
void Game::draw() {
- if (_needsRedraw)
- clearSurface();
+ if (_needsRedraw) {
+ // Load the Xeen background
+ Common::File f;
+ if (!f.open("back.raw"))
+ error("Could not load background");
+
+ Graphics::Surface s = getSurface();
+ f.read((byte *)s.getPixels(), s.w * s.h);
+ }
+
UIElement::draw();
}
Commit: 48a9c9b93c635c50a4bde06aef90080e94c8d08a
https://github.com/scummvm/scummvm/commit/48a9c9b93c635c50a4bde06aef90080e94c8d08a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:48+01:00
Commit Message:
MM: MM1: Change getSurface to return ManagedSurface
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views_enh/game.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index f2cd2a30757..773b15a50d7 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -214,12 +214,8 @@ void UIElement::addView() {
g_events->addView(this);
}
-Graphics::Surface UIElement::getSurface() const {
- if (_bounds.width() == SCREEN_W &&
- _bounds.height() == SCREEN_H)
- return *g_events->getScreen();
- else
- return g_events->getScreen()->getSubArea(_bounds);
+Graphics::ManagedSurface UIElement::getSurface() const {
+ return Graphics::ManagedSurface(*g_events->getScreen(), _bounds);
}
} // namespace MM1
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index a10e9365e22..985d08e5011 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -111,7 +111,7 @@ public:
/**
* Returns a surface for drawing the element
*/
- Graphics::Surface getSurface() const;
+ Graphics::ManagedSurface getSurface() const;
/**
* Draws the element
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 452024d8638..c756b257cd2 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -165,7 +165,7 @@ void GameView::drawTile() {
++section;
}
- Graphics::Surface surf = getSurface();
+ Graphics::ManagedSurface surf = getSurface();
const Common::Array<Graphics::ManagedSurface> &tiles =
maps._tiles[section];
const Graphics::ManagedSurface &tile = tiles[_tileIndex];
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index f06630960a2..897e838a030 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -37,7 +37,7 @@ TextView::TextView(const Common::String &name, UIElement *owner) :
}
void TextView::writeChar(char c) {
- Graphics::Surface s = getSurface();
+ Graphics::ManagedSurface s = getSurface();
g_globals->_font->drawChar(&s, c,
_textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
@@ -80,13 +80,13 @@ void TextView::newLine() {
}
void TextView::clearSurface() {
- Graphics::Surface s = getSurface();
+ Graphics::ManagedSurface s = getSurface();
s.fillRect(Common::Rect(s.w, s.h), 0);
_textPos.x = _textPos.y = 0;
}
void TextView::drawTextBorder() {
- Graphics::Surface surf = getSurface();
+ Graphics::ManagedSurface surf = getSurface();
clearSurface();
// Draw boxes in the four corners
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index 4589ee6b694..6ae2d3a5e5f 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -49,7 +49,7 @@ void Game::draw() {
if (!f.open("back.raw"))
error("Could not load background");
- Graphics::Surface s = getSurface();
+ Graphics::ManagedSurface s = getSurface();
f.read((byte *)s.getPixels(), s.w * s.h);
}
Commit: ed2d2d7713fbf29876c14be266e2843a5df8abe0
https://github.com/scummvm/scummvm/commit/ed2d2d7713fbf29876c14be266e2843a5df8abe0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Different view area for Enhanced mode
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views_enh/game.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 985d08e5011..40e287e98a3 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -108,6 +108,13 @@ public:
void addView(const Common::String &name);
void addView();
+ /**
+ * Sets the element's bounds
+ */
+ void setBounds(const Common::Rect &r) {
+ _bounds = r;
+ }
+
/**
* Returns a surface for drawing the element
*/
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 13bafe415b8..2486580fcac 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -30,6 +30,7 @@ namespace Views {
Game::Game() : TextView("Game"),
_view(this), _commands(this),
_messages(this), _party(this) {
+ _view.setBounds(Common::Rect(0, 0, 245, 128));
}
bool Game::msgFocus(const FocusMessage &msg) {
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index c756b257cd2..0825bc5c6bc 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -47,7 +47,6 @@ static uint16 ARR18[] = { 4, 5, 6, 7 };
static uint16 ARR19[] = { 8, 9, 10, 11 };
GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
- _bounds = Common::Rect(0, 0, 245, 128);
Common::fill(&_arr1[0], &_arr1[11], 0);
}
@@ -173,7 +172,7 @@ void GameView::drawTile() {
Common::Point pos(_destLeft * 4, (8 - _destTop) * 8);
Common::Rect r(_srcLeft * 4, 0, _srcLeft * 4 + _srcWidth * 8, tile.h);
- surf.copyRectToSurface(tile, pos.x, pos.y, r);
+ surf.blitFrom(tile, r, pos);
}
} // namespace Views
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index 6ae2d3a5e5f..af41810535b 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -30,6 +30,7 @@ namespace ViewsEnh {
Game::Game() : TextView("Game"),
_view(this) {
+ _view.setBounds(Common::Rect(8, 8, 224, 140));
}
bool Game::msgFocus(const FocusMessage &msg) {
Commit: a6f2260825df2b2faab433c6556c003482033c53
https://github.com/scummvm/scummvm/commit/a6f2260825df2b2faab433c6556c003482033c53
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Set up a simple palette to match the in-game colors
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/gfx/screen_decoder.cpp
engines/mm/mm1/gfx/screen_decoder.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/mm1.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 773b15a50d7..36cd99af1e1 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -58,7 +58,8 @@ void Events::runGame() {
Common::Event e;
for (;;) {
while (g_system->getEventManager()->pollEvent(e)) {
- if (e.type == Common::EVENT_QUIT)
+ if (e.type == Common::EVENT_QUIT ||
+ e.type == Common::EVENT_RETURN_TO_LAUNCHER)
return;
else
processEvent(e);
diff --git a/engines/mm/mm1/gfx/screen_decoder.cpp b/engines/mm/mm1/gfx/screen_decoder.cpp
index 77de9ce683e..dbcacc1d1e5 100644
--- a/engines/mm/mm1/gfx/screen_decoder.cpp
+++ b/engines/mm/mm1/gfx/screen_decoder.cpp
@@ -20,6 +20,9 @@
*/
#include "common/file.h"
+#include "common/system.h"
+#include "graphics/palette.h"
+#include "graphics/screen.h"
#include "mm/mm1/gfx/screen_decoder.h"
namespace MM {
@@ -56,6 +59,9 @@ bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
int index = 0;
int imgSize = w * h / 4;
+ byte indexes[4];
+ getPaletteIndexes(indexes);
+
// Decompress the image bytes
int x = 0;
while (x < (w / 4) && !stream.eos()) {
@@ -88,12 +94,40 @@ bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
for (int i = 0; i < w * h / 4; ++i, ++srcP) {
v = *srcP;
for (int j = 0; j < 4; ++j, v <<= 2)
- *destP++ = v >> 6;
+ *destP++ = indexes[v >> 6];
}
return true;
}
+void ScreenDecoder::getPaletteIndexes(byte indexes[4]) {
+ byte pal[PALETTE_SIZE];
+ g_system->getPaletteManager()->grabPalette(pal, 0, PALETTE_COUNT);
+
+ indexes[0] = 0;
+ indexes[1] = findPalette(pal, 168, 84, 0);
+ indexes[2] = findPalette(pal, 252, 252, 84);
+ indexes[3] = findPalette(pal, 0xff, 0xff, 0xff);
+}
+
+byte ScreenDecoder::findPalette(const byte *pal, byte r, byte g, byte b) {
+ int closestDiff = 0x7fffffff;
+ byte closest = 0;
+
+ for (int i = 0; i < PALETTE_COUNT; ++i, pal += 3) {
+ int diff = ABS((int)r - (int)pal[0]) +
+ ABS((int)g - (int)pal[1]) +
+ ABS((int)b - (int)pal[2]);
+ if (diff < closestDiff) {
+ closestDiff = diff;
+ closest = i;
+ }
+ }
+
+ return closest;
+}
+
+
} // namespace Gfx
} // End of namespace Xeen
} // End of namespace MM
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
index 86446b5e589..75763ffa398 100644
--- a/engines/mm/mm1/gfx/screen_decoder.h
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -32,6 +32,9 @@ namespace Gfx {
class ScreenDecoder : public Image::ImageDecoder {
private:
Graphics::Surface _surface;
+
+ void getPaletteIndexes(byte indexes[4]);
+ byte findPalette(const byte *pal, byte r, byte g, byte b);
public:
ScreenDecoder() {}
~ScreenDecoder() override;
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index fd931234dbd..e87b61f737b 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -73,7 +73,14 @@ bool MM1Engine::isEnhanced() const {
}
void MM1Engine::setupNormal() {
- Gfx::GFX::setEgaPalette(0);
+ byte pal[12];
+ pal[0] = pal[1] = pal[2] = 0;
+ pal[3] = 168; pal[4] = 84; pal[5] = 0;
+ pal[6] = 252; pal[7] = 252; pal[8] = 84;
+ pal[9] = pal[10] = pal[11] = 255;
+
+ g_system->getPaletteManager()->setPalette(pal, 0, 3);
+ g_system->getPaletteManager()->setPalette(&pal[9], 255, 1);
}
bool MM1Engine::setupEnhanced() {
@@ -105,5 +112,12 @@ bool MM1Engine::setupEnhanced() {
return true;
}
-} // End of namespace Xeen
-} // End of namespace MM
+bool MM1Engine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsReturnToLauncher) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index 2d1f2dd8d77..5a881f13eb9 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -51,6 +51,8 @@ public:
MM1Engine(OSystem *syst, const MightAndMagicGameDescription *gameDesc);
~MM1Engine() override;
+ bool hasFeature(EngineFeature f) const override;
+
/**
* Returns a random number
*/
Commit: 1e03780a76cd8427f09ec63b068319c809c8727f
https://github.com/scummvm/scummvm/commit/1e03780a76cd8427f09ec63b068319c809c8727f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Tweak placement of 3d view in enhanced mode
Changed paths:
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views_enh/game.cpp
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 0825bc5c6bc..590786ed071 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -169,8 +169,12 @@ void GameView::drawTile() {
maps._tiles[section];
const Graphics::ManagedSurface &tile = tiles[_tileIndex];
- Common::Point pos(_destLeft * 4, (8 - _destTop) * 8);
Common::Rect r(_srcLeft * 4, 0, _srcLeft * 4 + _srcWidth * 8, tile.h);
+ Common::Point pos(_destLeft * 4, (8 - _destTop) * 8);
+ pos.x -= _bounds.left;
+ pos.y -= _bounds.top;
+ if (_bounds.top != 0)
+ pos.y += 12;
surf.blitFrom(tile, r, pos);
}
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index af41810535b..bc6df1e7a7b 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -30,7 +30,7 @@ namespace ViewsEnh {
Game::Game() : TextView("Game"),
_view(this) {
- _view.setBounds(Common::Rect(8, 8, 224, 140));
+ _view.setBounds(Common::Rect(8, 15, 224, 130));
}
bool Game::msgFocus(const FocusMessage &msg) {
Commit: 6f640274c5bb22c96d2225b74522fe432b23c13f
https://github.com/scummvm/scummvm/commit/6f640274c5bb22c96d2225b74522fe432b23c13f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Wall collision checks and proper map exit checks
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 6f62bcc3f57..4e317c6f981 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -447,5 +447,6 @@ movement:
3: " IMPASSABLE "
4: " ROUGH SEAS "
5: " TOO WINDY! "
+ cant_swim: " CAN'T SWIM"
view:
darkness: " DARKNESS"
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 0441877e511..1432d46dc4a 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -21,12 +21,14 @@
#include "mm/mm1/game/view_base.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
namespace Game {
ViewBase::ViewBase(UIElement *owner) : Views::TextView("View", owner) {
+ Common::fill(&_arr2[0], &_arr2[8], 0);
}
void ViewBase::update() {
@@ -59,7 +61,9 @@ darkness:
bool ViewBase::msgAction(const ActionMessage &msg) {
switch (msg._action) {
case KEYBIND_FORWARDS:
- forward();
+ case KEYBIND_STRAFE_LEFT:
+ case KEYBIND_STRAFE_RIGHT:
+ forward(msg._action);
break;
case KEYBIND_BACKWARDS:
backwards();
@@ -103,13 +107,110 @@ void ViewBase::turnRight() {
update();
}
-void ViewBase::forward() {
- g_globals->_maps.forward();
+void ViewBase::forward(KeybindingAction action) {
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *g_globals->_maps._currentMap;
+
+ // Figure out direction mask
+ byte mask = maps._forwardMask;
+ if (action == KEYBIND_STRAFE_LEFT) {
+ mask = maps._leftMask;
+ } else if (action == KEYBIND_STRAFE_RIGHT) {
+ mask = maps._rightMask;
+ }
+
+ // Get the delta X/Y from the direction
+ Common::Point delta(0, 1);
+ switch (mask) {
+ case Maps::DIRMASK_E:
+ delta = Common::Point(1, 0);
+ break;
+ case Maps::DIRMASK_W:
+ delta = Common::Point(-1, 0);
+ break;
+ case Maps::DIRMASK_S:
+ delta = Common::Point(0, -1);
+ break;
+ default:
+ break;
+ }
+
+ // Check for obstructions
+ if (maps._currentWalls & mask) {
+ if (maps._currentState & 0x55 & mask) {
+ barrier();
+ return;
+ }
+ } else {
+ if (maps._currentState & 0x55 & mask) {
+ obstructed();
+ return;
+ }
+
+ int offset;
+ if (!(maps._currentWalls & mask & 0x55))
+ offset = 1;
+ else if (maps._currentWalls & mask & 0xaa)
+ offset = 2;
+ else
+ offset = 0;
+
+ if (map.dataByte(30 + offset) == 4 &&
+ !g_globals->_spells._s.walk_on_water) {
+ dialogVal(1);
+ dialogMessage(STRING["movement.obstructed.cant_swim"]);
+ return;
+ }
+ }
+
+ Common::fill(&_arr2[0], &_arr2[8], 0);
+
+ int maxVal = map.dataByte(29);
+ if (g_engine->getRandomNumber(maxVal) == maxVal)
+ _val1 = 1;
+
+ g_globals->_maps.step(delta);
update();
}
void ViewBase::backwards() {
- g_globals->_maps.backwards();
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *g_globals->_maps._currentMap;
+
+// Get the delta X/Y from the direction
+ Common::Point delta(0, -1);
+ switch (maps._backwardsMask) {
+ case Maps::DIRMASK_E:
+ delta = Common::Point(-1, 0);
+ break;
+ case Maps::DIRMASK_W:
+ delta = Common::Point(1, 0);
+ break;
+ case Maps::DIRMASK_S:
+ delta = Common::Point(0, 1);
+ break;
+ default:
+ break;
+ }
+
+ if (maps._currentWalls & maps._backwardsMask) {
+ dialogVal(1);
+ checkPartyDead();
+ return;
+ }
+ if (maps._currentState & 0x55 & maps._backwardsMask) {
+ dialogVal(1);
+ checkPartyDead();
+ return;
+ }
+
+ Common::fill(&_arr2[0], &_arr2[8], 0);
+
+ int maxVal = map.dataByte(29);
+ if (g_engine->getRandomNumber(maxVal) == maxVal)
+ _val1 = 1;
+
+ g_globals->_maps.step(delta);
update();
}
@@ -117,6 +218,30 @@ void ViewBase::obstructed() {
// TODO
}
+void ViewBase::barrier() {
+ // TODO
+}
+
+void ViewBase::dialogVal(int num) {
+ // TODO
+}
+
+void ViewBase::dialogMessage(const Common::String &msg) {
+ // TODO
+}
+
+void ViewBase::checkPartyDead() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if ((c._condition & (ASLEEP | STONE | DEAD | BAD_CONDITION)) == 0)
+ return;
+ }
+
+ // At this point, there's no good characters.
+ // So redirect to the death screen
+ replaceView("Dead");
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 5672e342008..b1a1a44234a 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -38,6 +38,8 @@ protected:
bool _isDark = false;
Common::String _message;
int _mapOffset = 0;
+ byte _arr2[8];
+ int _val1 = 0;
private:
/**
* Turn left
@@ -52,7 +54,7 @@ private:
/**
* Move forwards
*/
- void forward();
+ void forward(KeybindingAction action);
/**
* Move backwards
@@ -63,6 +65,19 @@ private:
* Forward movement is obstructed
*/
void obstructed();
+
+ /**
+ * Barrier blocking forward movement
+ */
+ void barrier();
+
+ void dialogVal(int num);
+ void dialogMessage(const Common::String &msg);
+
+ /**
+ * Checks whether the party is dead
+ */
+ void checkPartyDead();
public:
ViewBase(UIElement *owner);
virtual ~ViewBase() {}
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index ff4f1f24f22..a90010f6a43 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -263,46 +263,33 @@ void Maps::turnRight() {
_backwardsOffset = tempOffset;
}
-void Maps::forward() {
- // TODO: Properly implement this for
- // checking for obstructions and map changes
- switch (_forwardMask) {
- case DIRMASK_N:
- _mapPos.y++;
- break;
- case DIRMASK_S:
- _mapPos.y--;
- break;
- case DIRMASK_E:
- _mapPos.x++;
- break;
- case DIRMASK_W:
- _mapPos.x--;
- break;
- default:
- break;
+void Maps::step(const Common::Point &delta) {
+ _mapPos += delta;
+ int section = 0, id = 0;
+
+ if (_mapPos.x < 0) {
+ _mapPos.x = MAP_W - 1;
+ id = _currentMap->dataWord(16);
+ section = _currentMap->dataByte(14);
+ } else if (_mapPos.x >= MAP_W) {
+ _mapPos.x = 0;
+ id = _currentMap->dataWord(11);
+ section = _currentMap->dataByte(13);
+ } else if (_mapPos.y < 0) {
+ _mapPos.y = MAP_H - 1;
+ id = _currentMap->dataWord(17);
+ section = _currentMap->dataByte(19);
+ } else if (_mapPos.y >= MAP_H) {
+ _mapPos.y = 0;
+ id = _currentMap->dataWord(8);
+ section = _currentMap->dataByte(10);
+ } else {
+ return;
}
-}
-void Maps::backwards() {
- // TODO: Properly implement this for
- // checking for obstructions and map changes
- switch (_forwardMask) {
- case DIRMASK_N:
- _mapPos.y--;
- break;
- case DIRMASK_S:
- _mapPos.y++;
- break;
- case DIRMASK_E:
- _mapPos.x--;
- break;
- case DIRMASK_W:
- _mapPos.x++;
- break;
- default:
- break;
- }
+ // At this point, a new map is being entered
+ select(id, section);
+ loadTiles();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index b89ea4f6a10..45c0055a200 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -261,14 +261,9 @@ public:
void turnRight();
/**
- * Move forward
+ * Move a step
*/
- void forward();
-
- /**
- * Move backwards
- */
- void backwards();
+ void step(const Common::Point &delta);
};
} // namespace Maps
Commit: f0c78a8ffbb34b2b8b8887fd19b3c396d5f08bfa
https://github.com/scummvm/scummvm/commit/f0c78a8ffbb34b2b8b8887fd19b3c396d5f08bfa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Move checkPartyDead to Map class
Changed paths:
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map00.h
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 1432d46dc4a..b0b514f96a2 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -54,7 +54,20 @@ darkness:
_isDark = true;
}
- // Redraw the screen
+ // Encounter checks
+ _encounterFlag = false;
+ if (maps._currentState & 0x80) {
+ map.special();
+
+ } else if (_stepRandom) {
+ _encounterFlag = true;
+ _stepRandom = false;
+ addView("Encounter");
+ } else {
+ map.checkPartyDead();
+ }
+
+ // Flag to redraw the screen
redraw();
}
@@ -167,7 +180,7 @@ void ViewBase::forward(KeybindingAction action) {
int maxVal = map.dataByte(29);
if (g_engine->getRandomNumber(maxVal) == maxVal)
- _val1 = 1;
+ _stepRandom = true;
g_globals->_maps.step(delta);
update();
@@ -195,12 +208,12 @@ void ViewBase::backwards() {
if (maps._currentWalls & maps._backwardsMask) {
dialogVal(1);
- checkPartyDead();
+ map.checkPartyDead();
return;
}
if (maps._currentState & 0x55 & maps._backwardsMask) {
dialogVal(1);
- checkPartyDead();
+ map.checkPartyDead();
return;
}
@@ -208,7 +221,7 @@ void ViewBase::backwards() {
int maxVal = map.dataByte(29);
if (g_engine->getRandomNumber(maxVal) == maxVal)
- _val1 = 1;
+ _stepRandom = true;
g_globals->_maps.step(delta);
update();
@@ -230,18 +243,6 @@ void ViewBase::dialogMessage(const Common::String &msg) {
// TODO
}
-void ViewBase::checkPartyDead() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- if ((c._condition & (ASLEEP | STONE | DEAD | BAD_CONDITION)) == 0)
- return;
- }
-
- // At this point, there's no good characters.
- // So redirect to the death screen
- replaceView("Dead");
-}
-
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index b1a1a44234a..e6ce8bd38a4 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -39,7 +39,8 @@ protected:
Common::String _message;
int _mapOffset = 0;
byte _arr2[8];
- int _val1 = 0;
+ bool _stepRandom = false;
+ bool _encounterFlag = false;
private:
/**
* Turn left
@@ -74,10 +75,6 @@ private:
void dialogVal(int num);
void dialogMessage(const Common::String &msg);
- /**
- * Checks whether the party is dead
- */
- void checkPartyDead();
public:
ViewBase(UIElement *owner);
virtual ~ViewBase() {}
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 297d33047e9..d0807b8e6b9 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -22,6 +22,8 @@
#include "common/file.h"
#include "mm/mm1/maps/map.h"
#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/events.h"
namespace MM {
namespace MM1 {
@@ -75,6 +77,18 @@ void Map::loadOverlay() {
f.read(&_data[0], dataSize);
}
+void Map::checkPartyDead() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if ((c._condition & (ASLEEP | STONE | DEAD | BAD_CONDITION)) == 0)
+ return;
+ }
+
+ // At this point, there's no good characters.
+ // So redirect to the death screen
+ g_events->replaceView("Dead");
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index e0c0882ce36..b5f5c9e7db0 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -72,6 +72,11 @@ public:
*/
virtual void load();
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ virtual void special() = 0;
+
/**
* Gets the map name
*/
@@ -97,6 +102,12 @@ public:
uint16 dataWord(uint16 ofs) const {
return (uint16)_data[ofs] | ((uint16)_data[ofs + 1] << 8);
}
+
+ /**
+ * Checks whether the party is dead or out of action,
+ * and if so, switches to the death screen
+ */
+ void checkPartyDead();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 963a69a0ff0..91b7a45e9e7 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -25,7 +25,9 @@ namespace MM {
namespace MM1 {
namespace Maps {
+void Map00::special() {
+}
} // namespace Maps
} // namespace MM1
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index 3b3171fe8c4..1852144a9de 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -31,6 +31,11 @@ namespace Maps {
class Map00 : public Map {
public:
Map00(Maps *owner) : Map(owner, "sorpigal", 0x604) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ virtual void special();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 45c0055a200..a711557e645 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -46,6 +46,7 @@ enum DirMask {
class Map##INDEX : public Map { \
public: \
Map##INDEX(Maps *owner) : Map(owner, NAME, ID) {} \
+ void special() override {} \
}
PLACEHOLDER(01, "portsmit", 0xC03);
Commit: b03f7f056bd9c5661cd63b828baf0f9beb897f0a
https://github.com/scummvm/scummvm/commit/b03f7f056bd9c5661cd63b828baf0f9beb897f0a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Skeleton for special action methods in map 0
Changed paths:
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map00.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/game_view.cpp
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index b0b514f96a2..9cd550da8c2 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -35,9 +35,9 @@ void ViewBase::update() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
- _mapOffset = maps._mapPos.y * MAP_W + maps._mapPos.x;
- maps._currentWalls = map._walls[_mapOffset];
- maps._currentState = map._states[_mapOffset];
+ maps._mapOffset = maps._mapPos.y * MAP_W + maps._mapPos.x;
+ maps._currentWalls = map._walls[maps._mapOffset];
+ maps._currentState = map._states[maps._mapOffset];
_isDark = false;
if (maps._currentState & Maps::CELL_DARK) {
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index e6ce8bd38a4..ec9ea50799a 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -37,7 +37,6 @@ class ViewBase : public Views::TextView {
protected:
bool _isDark = false;
Common::String _message;
- int _mapOffset = 0;
byte _arr2[8];
bool _stepRandom = false;
bool _encounterFlag = false;
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index b5f5c9e7db0..c2a321cd751 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -45,7 +45,7 @@ enum CellState {
};
class Map {
-private:
+protected:
Common::String _name;
uint16 _id;
uint _mapId;
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 91b7a45e9e7..735a9b85de9 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -20,15 +20,56 @@
*/
#include "mm/mm1/maps/map00.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
namespace MM {
namespace MM1 {
namespace Maps {
void Map00::special() {
+ Maps &maps = g_globals->_maps;
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (maps._mapOffset == _data[51 + i] &&
+ (maps._forwardMask & _data[75 + i]) != 0) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ return;
+ }
+ }
+
+ // All other cells on the map are encounters
+ maps.clearSpecial();
+ g_events->addView("Encounter");
}
+void Map00::special00() {}
+void Map00::special01() {}
+void Map00::special02() {}
+void Map00::special03() {}
+void Map00::special04() {}
+void Map00::special05() {}
+void Map00::special06() {}
+void Map00::special07() {}
+void Map00::special08() {}
+void Map00::special09() {}
+void Map00::special10() {}
+void Map00::special11() {}
+void Map00::special12() {}
+void Map00::special13() {}
+void Map00::special14() {}
+void Map00::special15() {}
+void Map00::special16() {}
+void Map00::special17() {}
+void Map00::special18() {}
+void Map00::special19() {}
+void Map00::special20() {}
+void Map00::special21() {}
+void Map00::special22() {}
+void Map00::special23() {}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index 1852144a9de..a8420f4ccef 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -29,6 +29,59 @@ namespace MM1 {
namespace Maps {
class Map00 : public Map {
+ typedef void (Map00:: *SpecialFn)();
+private:
+ void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special17();
+ void special18();
+ void special19();
+ void special20();
+ void special21();
+ void special22();
+ void special23();
+
+ const SpecialFn SPECIAL_FN[24] = {
+ &Map00::special00,
+ &Map00::special01,
+ &Map00::special02,
+ &Map00::special03,
+ &Map00::special04,
+ &Map00::special05,
+ &Map00::special06,
+ &Map00::special07,
+ &Map00::special08,
+ &Map00::special09,
+ &Map00::special10,
+ &Map00::special11,
+ &Map00::special12,
+ &Map00::special13,
+ &Map00::special14,
+ &Map00::special15,
+ &Map00::special16,
+ &Map00::special17,
+ &Map00::special18,
+ &Map00::special19,
+ &Map00::special20,
+ &Map00::special21,
+ &Map00::special22,
+ &Map00::special23
+ };
public:
Map00(Maps *owner) : Map(owner, "sorpigal", 0x604) {}
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index a90010f6a43..2ee2e77fdae 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -292,6 +292,11 @@ void Maps::step(const Common::Point &delta) {
loadTiles();
}
+void Maps::clearSpecial() {
+ _currentState &= ~CELL_SPECIAL;
+ _currentMap->_states[_mapOffset] &= ~CELL_SPECIAL;
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index a711557e645..6eb0105585f 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -207,6 +207,7 @@ public:
Common::Array<Graphics::ManagedSurface> _tiles[3];
uint _mapId = (uint)-1;
Common::Point _mapPos;
+ uint _mapOffset = 0;
Map *_currentMap = nullptr;
byte _currentWalls = 0;
byte _currentState = 0;
@@ -265,6 +266,13 @@ public:
* Move a step
*/
void step(const Common::Point &delta);
+
+ /**
+ * Disables the special state of the current cell
+ * This is primiarily used for disabling cells
+ * that trigger combat after the first time
+ */
+ void clearSpecial();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 590786ed071..342fe03a53c 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -53,7 +53,7 @@ GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
void GameView::draw() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
- int mapOffset = _mapOffset;
+ int mapOffset = maps._mapOffset;
Common::fill(&_arr1[0], &_arr1[11], 0);
Commit: f6a1fe305a6817bb4dd69e6be649573192e457aa
https://github.com/scummvm/scummvm/commit/f6a1fe305a6817bb4dd69e6be649573192e457aa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Fix map 0 special cells check
Changed paths:
engines/mm/mm1/maps/map00.cpp
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 735a9b85de9..dffba001415 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -32,10 +32,15 @@ void Map00::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
- if (maps._mapOffset == _data[51 + i] &&
- (maps._forwardMask & _data[75 + i]) != 0) {
- // TODO: Some extra message code
- (this->*SPECIAL_FN[i])();
+ if (maps._mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (maps._forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
return;
}
}
@@ -45,30 +50,30 @@ void Map00::special() {
g_events->addView("Encounter");
}
-void Map00::special00() {}
-void Map00::special01() {}
-void Map00::special02() {}
-void Map00::special03() {}
-void Map00::special04() {}
-void Map00::special05() {}
-void Map00::special06() {}
-void Map00::special07() {}
-void Map00::special08() {}
-void Map00::special09() {}
-void Map00::special10() {}
-void Map00::special11() {}
-void Map00::special12() {}
-void Map00::special13() {}
-void Map00::special14() {}
-void Map00::special15() {}
-void Map00::special16() {}
-void Map00::special17() {}
-void Map00::special18() {}
-void Map00::special19() {}
-void Map00::special20() {}
-void Map00::special21() {}
-void Map00::special22() {}
-void Map00::special23() {}
+void Map00::special00() { warning("special00"); }
+void Map00::special01() { warning("special01"); }
+void Map00::special02() { warning("special02"); }
+void Map00::special03() { warning("special03"); }
+void Map00::special04() { warning("special04"); }
+void Map00::special05() { warning("special05"); }
+void Map00::special06() { warning("special06"); }
+void Map00::special07() { warning("special07"); }
+void Map00::special08() { warning("special08"); }
+void Map00::special09() { warning("special09"); }
+void Map00::special10() { warning("special10"); }
+void Map00::special11() { warning("special11"); }
+void Map00::special12() { warning("special12"); }
+void Map00::special13() { warning("special13"); }
+void Map00::special14() { warning("special14"); }
+void Map00::special15() { warning("special15"); }
+void Map00::special16() { warning("special16"); }
+void Map00::special17() { warning("special17"); }
+void Map00::special18() { warning("special18"); }
+void Map00::special19() { warning("special19"); }
+void Map00::special20() { warning("special20"); }
+void Map00::special21() { warning("special21"); }
+void Map00::special22() { warning("special22"); }
+void Map00::special23() { warning("special23"); }
} // namespace Maps
} // namespace MM1
Commit: 82b0e0fa95146143100c4cfa6e8608af0c5f4a62
https://github.com/scummvm/scummvm/commit/82b0e0fa95146143100c4cfa6e8608af0c5f4a62
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Set up dummy party on startup
Changed paths:
engines/mm/mm1/events.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 36cd99af1e1..159265b928d 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -52,6 +52,9 @@ void Events::runGame() {
_screen = new Graphics::Screen();
// Run the game
+ // ***DEBUG*** start directly in-game
+ for (uint i = 0; i < 6; ++i)
+ g_globals->_party.push_back(g_globals->_roster[i]);
g_globals->_maps.loadTown(Maps::SORPIGAL);
//addView("Title");
Commit: 028e38d0648a2ea98df7cbfbcf09fc04cdc7693c
https://github.com/scummvm/scummvm/commit/028e38d0648a2ea98df7cbfbcf09fc04cdc7693c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:49+01:00
Commit Message:
MM: MM1: Console commands pos and intangible
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views/game_view.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 46b53a2de03..34ee80855bc 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -24,6 +24,7 @@
#include "common/system.h"
#include "mm/mm1/console.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/events.h"
namespace MM {
namespace MM1 {
@@ -45,11 +46,14 @@ static int strToInt(const char *s) {
}
Console::Console() : GUI::Debugger() {
- registerCmd("dump_map", WRAP_METHOD(Console, Cmd_DumpMap));
- registerCmd("map_string", WRAP_METHOD(Console, Cmd_MapString));
+ registerCmd("dump_map", WRAP_METHOD(Console, cmdDumpMap));
+ registerCmd("map_string", WRAP_METHOD(Console, cmdMapString));
+ registerCmd("map", WRAP_METHOD(Console, cmdMap));
+ registerCmd("pos", WRAP_METHOD(Console, cmdPos));
+ registerCmd("intangible", WRAP_METHOD(Console, cmdIntangible));
}
-bool Console::Cmd_DumpMap(int argc, const char **argv) {
+bool Console::cmdDumpMap(int argc, const char **argv) {
Common::File f;
Common::OutSaveFile *dest;
@@ -123,7 +127,7 @@ bool Console::Cmd_DumpMap(int argc, const char **argv) {
return true;
}
-bool Console::Cmd_MapString(int argc, const char **argv) {
+bool Console::cmdMapString(int argc, const char **argv) {
Common::File f;
if (argc != 3) {
@@ -174,5 +178,45 @@ bool Console::Cmd_MapString(int argc, const char **argv) {
return true;
}
+bool Console::cmdMap(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("map mapId [ xp, yp ]\n");
+ return true;
+ } else {
+ Maps::Maps &maps = g_globals->_maps;
+
+ int mapId = strToInt(argv[1]);
+ int x = argc < 3 ? 8 : strToInt(argv[2]);
+ int y = argc < 4 ? 8 : strToInt(argv[3]);
+
+ maps.select(maps.getMap(mapId)->getId(), 0);
+ maps._mapPos.x = x;
+ maps._mapPos.y = y;
+ g_events->msgGame(GameMessage("UPDATE"));
+
+ return false;
+ }
+}
+
+bool Console::cmdPos(int argc, const char **argv) {
+ if (argc < 3) {
+ debugPrintf("pos xp, yp\n");
+ return true;
+ } else {
+ Maps::Maps &maps = g_globals->_maps;
+ maps._mapPos.x = strToInt(argv[1]);
+ maps._mapPos.y = strToInt(argv[2]);
+ g_events->msgGame(GameMessage("UPDATE"));
+
+ return false;
+ }
+}
+
+bool Console::cmdIntangible(int argc, const char **argv) {
+ g_globals->_intangible = (argc < 2) || strcmp(argv[1], "off");
+ debugPrintf("Intangibility is %s\n", g_globals->_intangible ? "on" : "off");
+ return true;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index 07bccdcde5b..b907c02437b 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -32,12 +32,27 @@ protected:
/**
* Used to dump a map's code and data
*/
- bool Cmd_DumpMap(int argc, const char **argv);
+ bool cmdDumpMap(int argc, const char **argv);
/**
* Prints a string from within a map's data segment
*/
- bool Cmd_MapString(int argc, const char **argv);
+ bool cmdMapString(int argc, const char **argv);
+
+ /**
+ * Toggles intangible mode, allowing walking through walls
+ */
+ bool cmdIntangible(int argc, const char **argv);
+
+ /**
+ * Jumps to a given map, and optionally a given position
+ */
+ bool cmdMap(int argc, const char **argv);
+
+ /**
+ * Changes the party's position in the current map
+ */
+ bool cmdPos(int argc, const char **argv);
public:
Console();
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 9cd550da8c2..2a8d7a9994d 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -100,12 +100,14 @@ bool ViewBase::msgFocus(const FocusMessage &msg) {
}
bool ViewBase::msgGame(const GameMessage &msg) {
- /*
if (msg._name == "DISPLAY") {
- replaceView(this);
+ replaceView("Game");
+ return true;
+ } else if (msg._name == "UPDATE") {
+ replaceView("Game");
+ update();
return true;
}
- */
return TextView::msgGame(msg);
}
@@ -149,30 +151,32 @@ void ViewBase::forward(KeybindingAction action) {
}
// Check for obstructions
- if (maps._currentWalls & mask) {
- if (maps._currentState & 0x55 & mask) {
- barrier();
- return;
- }
- } else {
- if (maps._currentState & 0x55 & mask) {
- obstructed();
- return;
- }
-
- int offset;
- if (!(maps._currentWalls & mask & 0x55))
- offset = 1;
- else if (maps._currentWalls & mask & 0xaa)
- offset = 2;
- else
- offset = 0;
-
- if (map.dataByte(30 + offset) == 4 &&
- !g_globals->_spells._s.walk_on_water) {
- dialogVal(1);
- dialogMessage(STRING["movement.obstructed.cant_swim"]);
- return;
+ if (!g_globals->_intangible) {
+ if (maps._currentWalls & mask) {
+ if (maps._currentState & 0x55 & mask) {
+ barrier();
+ return;
+ }
+ } else {
+ if (maps._currentState & 0x55 & mask) {
+ obstructed();
+ return;
+ }
+
+ int offset;
+ if (!(maps._currentWalls & mask & 0x55))
+ offset = 1;
+ else if (maps._currentWalls & mask & 0xaa)
+ offset = 2;
+ else
+ offset = 0;
+
+ if (map.dataByte(30 + offset) == 4 &&
+ !g_globals->_spells._s.walk_on_water) {
+ dialogVal(1);
+ dialogMessage(STRING["movement.obstructed.cant_swim"]);
+ return;
+ }
}
}
@@ -190,7 +194,7 @@ void ViewBase::backwards() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *g_globals->_maps._currentMap;
-// Get the delta X/Y from the direction
+ // Get the delta X/Y from the direction
Common::Point delta(0, -1);
switch (maps._backwardsMask) {
case Maps::DIRMASK_E:
@@ -206,15 +210,17 @@ void ViewBase::backwards() {
break;
}
- if (maps._currentWalls & maps._backwardsMask) {
- dialogVal(1);
- map.checkPartyDead();
- return;
- }
- if (maps._currentState & 0x55 & maps._backwardsMask) {
- dialogVal(1);
- map.checkPartyDead();
- return;
+ if (!g_globals->_intangible) {
+ if (maps._currentWalls & maps._backwardsMask) {
+ dialogVal(1);
+ map.checkPartyDead();
+ return;
+ }
+ if (maps._currentState & 0x55 & maps._backwardsMask) {
+ dialogVal(1);
+ map.checkPartyDead();
+ return;
+ }
}
Common::fill(&_arr2[0], &_arr2[8], 0);
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 7b4d31d2ad9..93e2ea30aec 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -41,6 +41,7 @@ public:
Maps::TownId _startingTown = Maps::SORPIGAL;
IntArray _partyChars;
Maps::Maps _maps;
+ bool _intangible = false; // Console flag
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 342fe03a53c..91b2732377b 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -53,7 +53,7 @@ GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
void GameView::draw() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
- int mapOffset = maps._mapOffset;
+ byte mapOffset = maps._mapOffset;
Common::fill(&_arr1[0], &_arr1[11], 0);
Commit: b3b95a65eb8571f1879f7bdfb3f0dc65b6409f05
https://github.com/scummvm/scummvm/commit/b3b95a65eb8571f1879f7bdfb3f0dc65b6409f05
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:50+01:00
Commit Message:
MM: MM1: Extracted font from executable
Changed paths:
A devtools/create_mm/files/mm1/font.bmp
A engines/mm/utils/bitmap_font.cpp
A engines/mm/utils/bitmap_font.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views/text_view.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/font.bmp b/devtools/create_mm/files/mm1/font.bmp
new file mode 100644
index 00000000000..1a7c9a58243
Binary files /dev/null and b/devtools/create_mm/files/mm1/font.bmp differ
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 7e3d3dd02bc..5dccd18fce8 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -49,12 +49,12 @@ bool Globals::load() {
if (!_strings.load("strings_en.yml"))
return false;
+ if (!_font.load("font.bmp"))
+ return false;
+
// Load roster
_roster.load();
- // Load the font
- _font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
-
return true;
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 93e2ea30aec..efc0feca6c8 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -23,6 +23,7 @@
#define MM1_GLOBALS_H
#include "graphics/font.h"
+#include "mm/utils/bitmap_font.h"
#include "mm/utils/strings_data.h"
#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/int_array.h"
@@ -36,12 +37,12 @@ class Globals : public GameState {
public:
StringsData _strings;
Roster _roster;
- const Graphics::Font *_font = nullptr;
Character *_currCharacter = nullptr;
Maps::TownId _startingTown = Maps::SORPIGAL;
IntArray _partyChars;
Maps::Maps _maps;
bool _intangible = false; // Console flag
+ BitmapFont _font;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 897e838a030..8522178e0e0 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -38,7 +38,7 @@ TextView::TextView(const Common::String &name, UIElement *owner) :
void TextView::writeChar(char c) {
Graphics::ManagedSurface s = getSurface();
- g_globals->_font->drawChar(&s, c,
+ g_globals->_font.drawChar(&s, c,
_textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
if (++_textPos.x == TEXT_W) {
@@ -104,8 +104,8 @@ void TextView::drawTextBorder() {
writeChar(x, TEXT_H - 2, '-');
}
for (int y = 3; y < TEXT_H - 3; ++y) {
- writeChar(1, y, '|');
- writeChar(TEXT_W - 2, y, '|');
+ writeChar(1, y, '!');
+ writeChar(TEXT_W - 2, y, '!');
}
}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index aadabca877a..55cfc7c28cb 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/mm
MODULE_OBJS := \
meta_engine.o \
+ utils/bitmap_font.o \
utils/engine_data.o \
utils/strings_data.o \
mm1/console.o \
diff --git a/engines/mm/utils/bitmap_font.cpp b/engines/mm/utils/bitmap_font.cpp
new file mode 100644
index 00000000000..89630b85617
--- /dev/null
+++ b/engines/mm/utils/bitmap_font.cpp
@@ -0,0 +1,72 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "image/bmp.h"
+#include "mm/utils/bitmap_font.h"
+
+namespace MM {
+
+bool BitmapFont::load(const Common::String &filename) {
+ Image::BitmapDecoder decoder;
+ Common::File f;
+ _startingChar = ' ';
+
+ if (!f.open(filename))
+ error("Could not open font");
+ if (!decoder.loadStream(f))
+ error("Could not decode font");
+
+ const Graphics::Surface &src = *decoder.getSurface();
+ assert(src.format.bytesPerPixel == 1);
+ assert((src.w % 8) == 0);
+ assert((src.h % 8) == 0);
+
+ // Set up a characters array
+ _chars.resize(97 - 32);
+
+ // Iterate through loading characters
+ Common::Rect r(8, 8);
+ int charsPerRow = src.w / 8;
+ for (uint idx = 0; idx < _chars.size(); ++idx) {
+ r.moveTo((idx % charsPerRow) * 8, (idx / charsPerRow) * 8);
+ Common::Rect charBounds(r.left, r.top, r.left + 8, r.bottom);
+
+ _chars[idx].create(8, 8, Graphics::PixelFormat::createFormatCLUT8());
+ _chars[idx].transBlitFrom(src, charBounds, Common::Rect(0, 0, 8, 8));
+ }
+
+ return true;
+}
+
+void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ const Graphics::ManagedSurface &c = _chars[chr - _startingChar];
+ for (int yCtr = 0; yCtr < c.h; ++yCtr) {
+ const byte *srcP = (const byte *)c.getBasePtr(0, yCtr);
+
+ for (int xCtr = 0; xCtr < c.w; ++xCtr, ++srcP) {
+ if (!*srcP)
+ dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
+ }
+ }
+}
+
+} // namespace MM
diff --git a/engines/mm/utils/bitmap_font.h b/engines/mm/utils/bitmap_font.h
new file mode 100644
index 00000000000..6eb28703420
--- /dev/null
+++ b/engines/mm/utils/bitmap_font.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_UTILS_BITMAP_FONT_H
+#define MM_UTILS_BITMAP_FONT_H
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "graphics/font.h"
+#include "graphics/managed_surface.h"
+
+namespace MM {
+
+/**
+ * Implements a font stored as a grid on a passed surface
+ */
+class BitmapFont : public Graphics::Font {
+private:
+ Common::Array<Graphics::ManagedSurface> _chars;
+ size_t _startingChar;
+public:
+ /**
+ * Constructor
+ */
+ BitmapFont() : _startingChar(' ') {}
+
+ /**
+ * Loads the font
+ */
+ bool load(const Common::String &filename);
+
+ /**
+ * Get the font height
+ */
+ int getFontHeight() const override { return 8; }
+
+ /**
+ * Get the maximum character width
+ */
+ int getMaxCharWidth() const override { return 8; }
+
+ /**
+ * Get the width of the given character
+ */
+ int getCharWidth(uint32 chr) const override { return 8; }
+
+ /**
+ * Draw a character
+ */
+ void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+ void drawChar(Graphics::ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const override {
+ return Graphics::Font::drawChar(dst, chr, x, y, color);
+ }
+};
+
+} // namespace MM
+
+#endif
Commit: 0db470e18491ffa07beaeb05d9d7c12f4b06c8b4
https://github.com/scummvm/scummvm/commit/0db470e18491ffa07beaeb05d9d7c12f4b06c8b4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:50+01:00
Commit Message:
MM: MM1: Popup messages for obstructions
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
engines/mm/utils/bitmap_font.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 4e317c6f981..88f0f81eab7 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -448,5 +448,6 @@ movement:
4: " ROUGH SEAS "
5: " TOO WINDY! "
cant_swim: " CAN'T SWIM"
+ barrier: " BARRIER! "
view:
darkness: " DARKNESS"
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 2a8d7a9994d..5b57919844d 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -154,12 +154,8 @@ void ViewBase::forward(KeybindingAction action) {
if (!g_globals->_intangible) {
if (maps._currentWalls & mask) {
if (maps._currentState & 0x55 & mask) {
- barrier();
- return;
- }
- } else {
- if (maps._currentState & 0x55 & mask) {
- obstructed();
+ obstructed(mask);
+ redraw();
return;
}
@@ -172,9 +168,16 @@ void ViewBase::forward(KeybindingAction action) {
offset = 0;
if (map.dataByte(30 + offset) == 4 &&
- !g_globals->_spells._s.walk_on_water) {
+ !g_globals->_spells._s.walk_on_water) {
dialogVal(1);
- dialogMessage(STRING["movement.obstructed.cant_swim"]);
+ _dialogMessage = STRING["movement.obstructed.cant_swim"];
+ redraw();
+ return;
+ }
+ } else {
+ if (maps._currentState & 0x55 & mask) {
+ barrier();
+ redraw();
return;
}
}
@@ -233,22 +236,31 @@ void ViewBase::backwards() {
update();
}
-void ViewBase::obstructed() {
- // TODO
+void ViewBase::obstructed(byte mask) {
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *maps._currentMap;
+ dialogVal(1);
+
+ int index = 32;
+ if (!(maps._currentWalls & mask & 0x55))
+ index = 31;
+ else if (!(maps._currentWalls & mask & 0xaa))
+ index = 30;
+
+ _dialogMessage = STRING[Common::String::format(
+ "movement.obstructed.%d", map.dataByte(index))];
+
}
void ViewBase::barrier() {
- // TODO
+ _dialogMessage = STRING["movement.obstructed.barrier"];
+ dialogVal(1);
}
void ViewBase::dialogVal(int num) {
// TODO
}
-void ViewBase::dialogMessage(const Common::String &msg) {
- // TODO
-}
-
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index ec9ea50799a..16e672495c9 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -36,7 +36,7 @@ namespace Game {
class ViewBase : public Views::TextView {
protected:
bool _isDark = false;
- Common::String _message;
+ Common::String _dialogMessage;
byte _arr2[8];
bool _stepRandom = false;
bool _encounterFlag = false;
@@ -64,7 +64,7 @@ private:
/**
* Forward movement is obstructed
*/
- void obstructed();
+ void obstructed(byte mask);
/**
* Barrier blocking forward movement
@@ -72,7 +72,6 @@ private:
void barrier();
void dialogVal(int num);
- void dialogMessage(const Common::String &msg);
public:
ViewBase(UIElement *owner);
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 91b2732377b..98abd7bcd50 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -51,14 +51,26 @@ GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
}
void GameView::draw() {
+ clearSurface();
+
+ if (!_isDark)
+ drawScene();
+
+ if (!_dialogMessage.empty()) {
+ drawDialogMessage();
+ _dialogMessage.clear();
+ } else if (_isDark) {
+ writeString(9, 7, STRING["view.darkness"]);
+ }
+}
+
+void GameView::drawScene() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
byte mapOffset = maps._mapOffset;
Common::fill(&_arr1[0], &_arr1[11], 0);
- clearSurface();
-
// Loop through four regions in front of the party
for (int dist = 0; dist < 4; ++dist,
mapOffset += maps._forwardOffset) {
@@ -179,6 +191,12 @@ void GameView::drawTile() {
surf.blitFrom(tile, r, pos);
}
+void GameView::drawDialogMessage() {
+ writeString(9, 6, " ");
+ writeString(9, 7, _dialogMessage);
+ writeString(9, 8, " ");
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index 2c038311620..8b9fbae7437 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -39,6 +39,16 @@ private:
* Draws a tile
*/
void drawTile();
+
+ /**
+ * Draws the scene
+ */
+ void drawScene();
+
+ /**
+ * Draws the dialog message
+ */
+ void drawDialogMessage();
public:
GameView(UIElement *owner);
virtual ~GameView() {}
diff --git a/engines/mm/utils/bitmap_font.cpp b/engines/mm/utils/bitmap_font.cpp
index 89630b85617..018a29c2a4e 100644
--- a/engines/mm/utils/bitmap_font.cpp
+++ b/engines/mm/utils/bitmap_font.cpp
@@ -63,8 +63,8 @@ void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint
const byte *srcP = (const byte *)c.getBasePtr(0, yCtr);
for (int xCtr = 0; xCtr < c.w; ++xCtr, ++srcP) {
- if (!*srcP)
- dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
+ dst->hLine(x + xCtr, y + yCtr, x + xCtr,
+ *srcP ? 0 : color);
}
}
}
Commit: 2fe7c8cc49312e537a6b3bc44753464de9e3e7f0
https://github.com/scummvm/scummvm/commit/2fe7c8cc49312e537a6b3bc44753464de9e3e7f0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:50+01:00
Commit Message:
MM: MM1: Added stubbed Sound class
Changed paths:
A engines/mm/mm1/sound.cpp
A engines/mm/mm1/sound.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 5b57919844d..1d8a8cca02a 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -22,6 +22,7 @@
#include "mm/mm1/game/view_base.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -169,7 +170,7 @@ void ViewBase::forward(KeybindingAction action) {
if (map.dataByte(30 + offset) == 4 &&
!g_globals->_spells._s.walk_on_water) {
- dialogVal(1);
+ Sound::sound(SOUND_OBSTRUCTED);
_dialogMessage = STRING["movement.obstructed.cant_swim"];
redraw();
return;
@@ -215,12 +216,12 @@ void ViewBase::backwards() {
if (!g_globals->_intangible) {
if (maps._currentWalls & maps._backwardsMask) {
- dialogVal(1);
+ Sound::sound(SOUND_OBSTRUCTED);
map.checkPartyDead();
return;
}
if (maps._currentState & 0x55 & maps._backwardsMask) {
- dialogVal(1);
+ Sound::sound(SOUND_OBSTRUCTED);
map.checkPartyDead();
return;
}
@@ -239,7 +240,7 @@ void ViewBase::backwards() {
void ViewBase::obstructed(byte mask) {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
- dialogVal(1);
+ Sound::sound(SOUND_OBSTRUCTED);
int index = 32;
if (!(maps._currentWalls & mask & 0x55))
@@ -254,11 +255,7 @@ void ViewBase::obstructed(byte mask) {
void ViewBase::barrier() {
_dialogMessage = STRING["movement.obstructed.barrier"];
- dialogVal(1);
-}
-
-void ViewBase::dialogVal(int num) {
- // TODO
+ Sound::sound(SOUND_OBSTRUCTED);
}
} // namespace Game
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 16e672495c9..e7ed92ee0b7 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -71,8 +71,6 @@ private:
*/
void barrier();
- void dialogVal(int num);
-
public:
ViewBase(UIElement *owner);
virtual ~ViewBase() {}
diff --git a/engines/mm/mm1/sound.cpp b/engines/mm/mm1/sound.cpp
new file mode 100644
index 00000000000..4383e5a4cf9
--- /dev/null
+++ b/engines/mm/mm1/sound.cpp
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/textconsole.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+
+void Sound::sound(SoundId soundNum) {
+ warning("TODO: sound %d", (int)soundNum);
+}
+
+void Sound::sound2(SoundId soundNum) {
+ warning("TODO: sound2 %d", (int)soundNum);
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
new file mode 100644
index 00000000000..c2da00b5930
--- /dev/null
+++ b/engines/mm/mm1/sound.h
@@ -0,0 +1,39 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_MM1_SOUND_H
+#define MM_MM1_SOUND_H
+
+namespace MM {
+namespace MM1 {
+
+enum SoundId { SOUND_OBSTRUCTED = 1 };
+
+class Sound {
+public:
+ static void sound(SoundId soundNum);
+ static void sound2(SoundId soundNum);
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 55cfc7c28cb..baeebe604c0 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS := \
mm1/globals.o \
mm1/meta_engine.o \
mm1/mm1.o \
+ mm1/sound.o \
mm1/data/char.o \
mm1/data/game_state.o \
mm1/data/roster.o \
Commit: 69dc7aac4d141ec9cd2ef99b23f40bb31c3172c6
https://github.com/scummvm/scummvm/commit/69dc7aac4d141ec9cd2ef99b23f40bb31c3172c6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:50+01:00
Commit Message:
MM: MM1: Fixes to drawing view walls
Changed paths:
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 98abd7bcd50..c75852976ec 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -47,7 +47,7 @@ static uint16 ARR18[] = { 4, 5, 6, 7 };
static uint16 ARR19[] = { 8, 9, 10, 11 };
GameView::GameView(UIElement *owner) : Game::ViewBase(owner) {
- Common::fill(&_arr1[0], &_arr1[11], 0);
+ Common::fill(&_drawFlags[0], &_drawFlags[10], 0);
}
void GameView::draw() {
@@ -69,7 +69,7 @@ void GameView::drawScene() {
Maps::Map &map = *maps._currentMap;
byte mapOffset = maps._mapOffset;
- Common::fill(&_arr1[0], &_arr1[11], 0);
+ Common::fill(&_drawFlags[0], &_drawFlags[10], 0);
// Loop through four regions in front of the party
for (int dist = 0; dist < 4; ++dist,
@@ -87,16 +87,16 @@ void GameView::drawScene() {
_destLeft = ARR7[dist];
_destTop = ARR1[dist];
_srcLeft = ARR14[dist];
- _arr1[dist + 1]++;
+ _drawFlags[dist + 1]++;
drawTile();
} else {
_mask = wallsLeft & maps._forwardMask;
if (_mask) {
_tileIndex = ARR19[dist];
- _arr1[dist + 1]++;
+ _drawFlags[dist + 1]++;
- if (_arr1[dist]) {
+ if (_drawFlags[dist]) {
_srcWidth = ARR5[dist];
_srcPitch = ARR13[dist];
_destLeft = ARR7[dist];
@@ -123,16 +123,16 @@ void GameView::drawScene() {
_destLeft = ARR9[dist];
_destTop = ARR1[dist];
_srcLeft = ARR14[dist];
- _arr1[dist + 1]++;
+ _drawFlags[dist + 6]++;
drawTile();
} else {
_mask = wallsRight & maps._forwardMask;
if (_mask) {
_tileIndex = ARR19[dist];
- _arr1[6 + dist]++;
+ _drawFlags[6 + dist]++;
- if (_arr1[5 + dist]) {
+ if (_drawFlags[5 + dist]) {
_srcWidth = ARR5[dist];
_srcPitch = ARR13[dist];
_destLeft = ARR10[dist];
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index 8b9fbae7437..f96bd1de1f9 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -33,7 +33,7 @@ private:
int _tileIndex = 0, _srcWidth = 0, _srcPitch = 0;
int _destLeft = 0, _destTop = 0, _srcLeft = 0;
byte _mask = 0;
- byte _arr1[11];
+ byte _drawFlags[10];
private:
/**
* Draws a tile
Commit: 6d674ca387dc340eb3dd5891d62260748d24d020
https://github.com/scummvm/scummvm/commit/6d674ca387dc340eb3dd5891d62260748d24d020
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:50+01:00
Commit Message:
MM: MM1: Fix moving backwards
Changed paths:
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 1d8a8cca02a..dcd22b6c0ea 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -136,20 +136,7 @@ void ViewBase::forward(KeybindingAction action) {
}
// Get the delta X/Y from the direction
- Common::Point delta(0, 1);
- switch (mask) {
- case Maps::DIRMASK_E:
- delta = Common::Point(1, 0);
- break;
- case Maps::DIRMASK_W:
- delta = Common::Point(-1, 0);
- break;
- case Maps::DIRMASK_S:
- delta = Common::Point(0, -1);
- break;
- default:
- break;
- }
+ Common::Point delta = getMoveDelta(mask);
// Check for obstructions
if (!g_globals->_intangible) {
@@ -197,22 +184,7 @@ void ViewBase::forward(KeybindingAction action) {
void ViewBase::backwards() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *g_globals->_maps._currentMap;
-
- // Get the delta X/Y from the direction
- Common::Point delta(0, -1);
- switch (maps._backwardsMask) {
- case Maps::DIRMASK_E:
- delta = Common::Point(-1, 0);
- break;
- case Maps::DIRMASK_W:
- delta = Common::Point(1, 0);
- break;
- case Maps::DIRMASK_S:
- delta = Common::Point(0, 1);
- break;
- default:
- break;
- }
+ Common::Point delta = getMoveDelta(maps._backwardsMask);
if (!g_globals->_intangible) {
if (maps._currentWalls & maps._backwardsMask) {
@@ -237,6 +209,19 @@ void ViewBase::backwards() {
update();
}
+Common::Point ViewBase::getMoveDelta(byte mask) const {
+ switch (mask) {
+ case Maps::DIRMASK_E:
+ return Common::Point(1, 0);
+ case Maps::DIRMASK_W:
+ return Common::Point(-1, 0);
+ case Maps::DIRMASK_S:
+ return Common::Point(0, -1);
+ default:
+ return Common::Point(0, 1);
+ }
+}
+
void ViewBase::obstructed(byte mask) {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index e7ed92ee0b7..d106bc04411 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -61,6 +61,11 @@ private:
*/
void backwards();
+ /**
+ * Gets the moveement delta given a direction mask
+ */
+ Common::Point getMoveDelta(byte mask) const;
+
/**
* Forward movement is obstructed
*/
Commit: 58f0b79b6850a54c920ad107771112d66006316e
https://github.com/scummvm/scummvm/commit/58f0b79b6850a54c920ad107771112d66006316e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:50+01:00
Commit Message:
MM: MM1: Mostly implement bash
Changed paths:
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/sound.h
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index dcd22b6c0ea..2422a07b788 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -19,9 +19,11 @@
*
*/
+#include "common/util.h"
#include "mm/mm1/game/view_base.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
namespace MM {
@@ -88,6 +90,9 @@ bool ViewBase::msgAction(const ActionMessage &msg) {
case KEYBIND_TURN_RIGHT:
turnRight();
break;
+ case KEYBIND_BASH:
+ bash();
+ break;
default:
return TextView::msgAction(msg);
}
@@ -243,6 +248,50 @@ void ViewBase::barrier() {
Sound::sound(SOUND_OBSTRUCTED);
}
+void ViewBase::bash() {
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *maps._currentMap;
+
+ if (!(maps._currentState & 0x55 & maps._forwardMask) ||
+ !(maps._currentWalls & maps._forwardMask)) {
+ // No forward obstruction, so simply move forward
+ forward(KEYBIND_FORWARDS);
+ } else {
+ int index = 32;
+ if (!(maps._currentWalls & maps._forwardMask & 0x55))
+ index = 31;
+ else if (!(maps._currentWalls & maps._forwardMask & 0x55))
+ index = 30;
+
+ if (map.dataByte(index) != 1) {
+ forward(KEYBIND_FORWARDS);
+ } else {
+ Sound::sound(SOUND_OBSTRUCTED);
+
+ uint might = g_engine->getRandomNumber(100);
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ might += g_globals->_party[i]._mgt;
+ might = MIN(might, 255U);
+
+ // Check for busting
+ uint threshold = map.dataByte(45);
+ if (threshold && might >= threshold) {
+ map._states[maps._mapOffset + maps._forwardMask] ^=
+ (maps._forwardMask & 0x55);
+ maps._currentState = map._states[maps._mapOffset + maps._forwardMask];
+ }
+
+ // Check for trap being triggered
+ if (g_engine->getRandomNumber(100) >= map.dataByte(48)) {
+ warning("TODO: trigger trap");
+
+ } else {
+ forward(KEYBIND_FORWARDS);
+ }
+ }
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index d106bc04411..955f762a68e 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -76,6 +76,10 @@ private:
*/
void barrier();
+ /**
+ * Bash
+ */
+ void bash();
public:
ViewBase(UIElement *owner);
virtual ~ViewBase() {}
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
index c2da00b5930..b8b22295741 100644
--- a/engines/mm/mm1/sound.h
+++ b/engines/mm/mm1/sound.h
@@ -25,7 +25,7 @@
namespace MM {
namespace MM1 {
-enum SoundId { SOUND_OBSTRUCTED = 1 };
+enum SoundId { SOUND_OBSTRUCTED = 1, SOUND_BASH = 2 };
class Sound {
public:
Commit: d06ce93568133df52e5b1d9c7324264e12169dee
https://github.com/scummvm/scummvm/commit/d06ce93568133df52e5b1d9c7324264e12169dee
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:50+01:00
Commit Message:
MM: MM1: Display of party, beginnings of Order command
Changed paths:
A engines/mm/mm1/views/order.cpp
A engines/mm/mm1/views/order.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game.h
engines/mm/mm1/views/game_party.cpp
engines/mm/mm1/views/game_party.h
engines/mm/mm1/views/view_characters.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 88f0f81eab7..a875e260fe9 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -37,6 +37,9 @@ dialogs:
option3: "'#'.......GO TO TOWN"
copyright1: "COPR. 1986,1987-JON VAN CANEGHEM"
copyright2: "ALL RIGHTS RESERVED"
+ order:
+ title: " RE-ORDER PARTY NEW 1 2 3 4 5 6"
+ old: "OLD ^"
protect:
title: "PROTECT: SPELLS CURRENTLY ACTIVE"
protection: "PROTECTION FROM"
@@ -69,7 +72,6 @@ dialogs:
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
- legend2: "'ESC' TO GO BACK"
view_character:
rename: "(CTRL)-'N' RE-NAME CHARACTER"
delete: "(CTRL)-'D' DELETE CHARACTER"
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 40e287e98a3..485a3d070f7 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -64,6 +64,10 @@ protected:
Common::Rect _bounds;
bool _needsRedraw = true;
Common::String _name;
+protected:
+ Common::Rect getLineBounds(int line1, int line2) const {
+ return Common::Rect(0, line1 * 8, 320, (line2 + 1) * 8);
+ }
private:
/**
* Outer method for doing drawing
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 3587bed4b6e..5e47dbeb146 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -28,6 +28,7 @@
#include "mm/mm1/views/game.h"
#include "mm/mm1/views/inn.h"
#include "mm/mm1/views/main_menu.h"
+#include "mm/mm1/views/order.h"
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
@@ -44,6 +45,7 @@ private:
Views::Game _game;
Views::Inn _inn;
Views::MainMenu _mainMenu;
+ Views::Order _order;
Views::Protect _protect;
Views::QuickRef _quickRef;
Views::Title _title;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 2486580fcac..75022dfb5ec 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -28,8 +28,7 @@ namespace MM1 {
namespace Views {
Game::Game() : TextView("Game"),
- _view(this), _commands(this),
- _messages(this), _party(this) {
+ _view(this), _commands(this), _party(this) {
_view.setBounds(Common::Rect(0, 0, 245, 128));
}
@@ -40,17 +39,22 @@ bool Game::msgFocus(const FocusMessage &msg) {
bool Game::msgUnfocus(const UnfocusMessage &msg) {
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
- return true;
+ return TextView::msgUnfocus(msg);
}
void Game::draw() {
if (_needsRedraw)
clearSurface();
- UIElement::draw();
+ TextView::draw();
}
-bool Game::msgKeypress(const KeypressMessage &msg) {
- return true;
+bool Game::msgAction(const ActionMessage &msg) {
+ if (msg._action == KEYBIND_ORDER) {
+ g_events->msgGame(GameMessage("ORDER"));
+ return true;
+ }
+
+ return TextView::msgAction(msg);
}
bool Game::msgGame(const GameMessage &msg) {
diff --git a/engines/mm/mm1/views/game.h b/engines/mm/mm1/views/game.h
index b84cf900c6e..56266936127 100644
--- a/engines/mm/mm1/views/game.h
+++ b/engines/mm/mm1/views/game.h
@@ -24,7 +24,6 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/game_commands.h"
-#include "mm/mm1/views/game_messages.h"
#include "mm/mm1/views/game_party.h"
#include "mm/mm1/views/game_view.h"
@@ -35,7 +34,6 @@ namespace Views {
class Game : public TextView {
private:
GameCommands _commands;
- GameMessages _messages;
GameParty _party;
GameView _view;
public:
@@ -45,7 +43,7 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
};
diff --git a/engines/mm/mm1/views/game_party.cpp b/engines/mm/mm1/views/game_party.cpp
index c84616ea732..fee5edd1199 100644
--- a/engines/mm/mm1/views/game_party.cpp
+++ b/engines/mm/mm1/views/game_party.cpp
@@ -26,7 +26,20 @@ namespace MM {
namespace MM1 {
namespace Views {
+GameParty::GameParty(UIElement *owner) : TextView("GameParty", owner) {
+ _bounds = getLineBounds(17, 19);
+}
+
void GameParty::draw() {
+ clearSurface();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ writeChar((i % 2) * 21, i / 2,
+ c._condition ? '*' : ' ');
+ writeString(Common::String::format("%d) %s",
+ i + 1, c._name));
+ }
}
bool GameParty::msgKeypress(const KeypressMessage &msg) {
diff --git a/engines/mm/mm1/views/game_party.h b/engines/mm/mm1/views/game_party.h
index c6c087489d3..acfc1924f37 100644
--- a/engines/mm/mm1/views/game_party.h
+++ b/engines/mm/mm1/views/game_party.h
@@ -30,7 +30,7 @@ namespace Views {
class GameParty : public TextView {
public:
- GameParty(UIElement *owner) : TextView("GameParty", owner) {}
+ GameParty(UIElement *owner);
virtual ~GameParty() {}
void draw() override;
diff --git a/engines/mm/mm1/views/order.cpp b/engines/mm/mm1/views/order.cpp
new file mode 100644
index 00000000000..be2991d91cc
--- /dev/null
+++ b/engines/mm/mm1/views/order.cpp
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/order.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Order::Order() : TextView("Order") {
+ _bounds = getLineBounds(21, 24);
+}
+
+bool Order::msgGame(const GameMessage &msg) {
+ if (msg._name == "ORDER" && g_globals->_party.size() > 1) {
+ // Show the dialog
+ addView(this);
+ return true;
+ }
+
+ return false;
+}
+
+bool Order::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ return true;
+ }
+
+ return true;
+}
+
+void Order::draw() {
+ clearSurface();
+ writeString(0, 0, STRING["dialogs.order.title"]);
+ writeString(17, 1, STRING["dialogs.order.old"]);
+ writeString(0, 2, STRING["dialogs.misc.go_back"]);
+
+ // TODO
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/order.h b/engines/mm/mm1/views/order.h
new file mode 100644
index 00000000000..381e5b44761
--- /dev/null
+++ b/engines/mm/mm1/views/order.h
@@ -0,0 +1,45 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ORDER_H
+#define MM1_VIEWS_ORDER_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Order : public TextView {
+public:
+ Order();
+ virtual ~Order() {}
+
+ bool msgGame(const GameMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void draw() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index fbc3d0bb5b3..11502fb8267 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -69,7 +69,7 @@ void ViewCharacters::draw() {
writeString(6, 22, Common::String::format(
STRING["dialogs.view_characters.legend1"].c_str(),
'A' + (int)_charIndexes.size() - 1));
- writeString(12, 24, STRING["dialogs.view_characters.legend2"]);
+ writeString(12, 24, STRING["dialogs.misc.go_back"]);
}
bool ViewCharacters::msgKeypress(const KeypressMessage &msg) {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index baeebe604c0..83baf636198 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -28,6 +28,7 @@ MODULE_OBJS := \
mm1/views/game_view.o \
mm1/views/inn.o \
mm1/views/main_menu.o \
+ mm1/views/order.o \
mm1/views/protect.o \
mm1/views/quick_ref.o \
mm1/views/title.o \
Commit: addfc3291b3168f2283442e72432081173d9b396
https://github.com/scummvm/scummvm/commit/addfc3291b3168f2283442e72432081173d9b396
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Finished Order command
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/order.cpp
engines/mm/mm1/views/order.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index a875e260fe9..af4ac2d5ab5 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -39,7 +39,7 @@ dialogs:
copyright2: "ALL RIGHTS RESERVED"
order:
title: " RE-ORDER PARTY NEW 1 2 3 4 5 6"
- old: "OLD ^"
+ old: "OLD"
protect:
title: "PROTECT: SPELLS CURRENTLY ACTIVE"
protection: "PROTECTION FROM"
diff --git a/engines/mm/mm1/views/order.cpp b/engines/mm/mm1/views/order.cpp
index be2991d91cc..b085fa2b242 100644
--- a/engines/mm/mm1/views/order.cpp
+++ b/engines/mm/mm1/views/order.cpp
@@ -43,7 +43,34 @@ bool Order::msgGame(const GameMessage &msg) {
bool Order::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
close();
- return true;
+
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
+ !_indexes.empty()) {
+ _indexes.remove_at(_indexes.size() - 1);
+ redraw();
+
+ } else if (msg.ascii >= '1' && msg.ascii <= '6') {
+ // Check for the index already existing
+ for (uint i = 0; i < _indexes.size(); ++i) {
+ if (_indexes[i] == (uint)(msg.ascii - '0'))
+ return true;
+ }
+
+ _indexes.push_back(msg.ascii - '0');
+
+ if (_indexes.size() < g_globals->_party.size()) {
+ // Redraw with the new entry added
+ redraw();
+ } else {
+ // Reached the party size
+ Common::Array<Character> oldParty = g_globals->_party;
+ g_globals->_party.clear();
+
+ for (uint i = 0; i < _indexes.size(); ++i)
+ g_globals->_party.push_back(oldParty[_indexes[i] - 1]);
+
+ close();
+ }
}
return true;
@@ -52,10 +79,14 @@ bool Order::msgKeypress(const KeypressMessage &msg) {
void Order::draw() {
clearSurface();
writeString(0, 0, STRING["dialogs.order.title"]);
- writeString(17, 1, STRING["dialogs.order.old"]);
writeString(0, 2, STRING["dialogs.misc.go_back"]);
+ writeString(17, 1, STRING["dialogs.order.old"]);
- // TODO
+ _textPos.x = 21;
+ for (uint i = 0; i < _indexes.size(); ++i)
+ writeString(Common::String::format(
+ " %d ", _indexes[i]));
+ writeChar('^');
}
} // namespace Views
diff --git a/engines/mm/mm1/views/order.h b/engines/mm/mm1/views/order.h
index 381e5b44761..dc9a927f968 100644
--- a/engines/mm/mm1/views/order.h
+++ b/engines/mm/mm1/views/order.h
@@ -29,6 +29,8 @@ namespace MM1 {
namespace Views {
class Order : public TextView {
+private:
+ Common::Array<uint> _indexes;
public:
Order();
virtual ~Order() {}
Commit: ccb355f62e6c75eadf3a9c635544fc51d212ddec
https://github.com/scummvm/scummvm/commit/ccb355f62e6c75eadf3a9c635544fc51d212ddec
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Added message info display
Changed paths:
A engines/mm/mm1/game/search.cpp
A engines/mm/mm1/game/search.h
engines/mm/mm1/events.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game.h
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/game_messages.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 485a3d070f7..0d6922f948d 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -25,6 +25,7 @@
#include "common/array.h"
#include "common/events.h"
#include "common/stack.h"
+#include "common/str-array.h"
#include "graphics/screen.h"
#include "mm/mm1/meta_engine.h"
@@ -56,6 +57,17 @@ struct GameMessage : public Message {
_name(name) {}
};
+struct InfoMessage : public Message {
+ Common::StringArray _lines;
+ InfoMessage() : Message() {}
+ InfoMessage(const Common::String &str) : Message() {
+ _lines.push_back("");
+ _lines.push_back(str);
+ }
+ InfoMessage(const Common::StringArray &lines) :
+ Message(), _lines(lines) {}
+};
+
class UIElement {
friend class Events;
protected:
@@ -156,6 +168,7 @@ public:
MESSAGE(Keypress);
MESSAGE(Action);
MESSAGE(Game);
+ MESSAGE(Info);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/game/search.cpp b/engines/mm/mm1/game/search.cpp
new file mode 100644
index 00000000000..526372a12f4
--- /dev/null
+++ b/engines/mm/mm1/game/search.cpp
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/sound.h"
+#include "mm/mm1/game/search.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+void Search::execute() {
+ // TODO: Handle properly
+ g_events->msgInfo(InfoMessage("YOU FOUND... NOTHING"));
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/search.h b/engines/mm/mm1/game/search.h
new file mode 100644
index 00000000000..6c0c92bae36
--- /dev/null
+++ b/engines/mm/mm1/game/search.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_SEARCH_H
+#define MM1_GAME_SEARCH_H
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+struct Search {
+ static void execute();
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 2422a07b788..ba2dfc8f4de 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -71,7 +71,7 @@ darkness:
}
// Flag to redraw the screen
- redraw();
+ g_events->redraw();
}
bool ViewBase::msgAction(const ActionMessage &msg) {
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 75022dfb5ec..fb86ded40cc 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -22,13 +22,14 @@
#include "mm/mm1/views/game.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/meta_engine.h"
+#include "mm/mm1/game/search.h"
namespace MM {
namespace MM1 {
namespace Views {
Game::Game() : TextView("Game"),
- _view(this), _commands(this), _party(this) {
+ _view(this), _commands(this), _messages(this), _party(this) {
_view.setBounds(Common::Rect(0, 0, 245, 128));
}
@@ -49,9 +50,13 @@ void Game::draw() {
}
bool Game::msgAction(const ActionMessage &msg) {
- if (msg._action == KEYBIND_ORDER) {
+ switch (msg._action) {
+ case KEYBIND_ORDER:
g_events->msgGame(GameMessage("ORDER"));
return true;
+ case KEYBIND_SEARCH:
+ MM1::Game::Search::execute();
+ break;
}
return TextView::msgAction(msg);
diff --git a/engines/mm/mm1/views/game.h b/engines/mm/mm1/views/game.h
index 56266936127..45ad7673fd8 100644
--- a/engines/mm/mm1/views/game.h
+++ b/engines/mm/mm1/views/game.h
@@ -24,6 +24,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/game_commands.h"
+#include "mm/mm1/views/game_messages.h"
#include "mm/mm1/views/game_party.h"
#include "mm/mm1/views/game_view.h"
@@ -34,6 +35,7 @@ namespace Views {
class Game : public TextView {
private:
GameCommands _commands;
+ GameMessages _messages;
GameParty _party;
GameView _view;
public:
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 9cf4faacace..8baf5a7add0 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/util.h"
#include "mm/mm1/views/game_messages.h"
#include "mm/mm1/globals.h"
@@ -26,11 +27,23 @@ namespace MM {
namespace MM1 {
namespace Views {
+GameMessages::GameMessages(UIElement *owner) :
+ TextView("GameMessages", owner) {
+ _bounds = getLineBounds(20, 24);
+}
+
void GameMessages::draw() {
+ clearSurface();
+ for (uint i = 0; i < MIN(_lines.size(), 4U); ++i)
+ writeString(0, i, _lines[i]);
+
+ _lines.clear();
}
-bool GameMessages::msgKeypress(const KeypressMessage &msg) {
- return false;
+bool GameMessages::msgInfo(const InfoMessage &msg) {
+ _lines = msg._lines;
+ redraw();
+ return true;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
index a6c102c63e0..73b432685c3 100644
--- a/engines/mm/mm1/views/game_messages.h
+++ b/engines/mm/mm1/views/game_messages.h
@@ -22,6 +22,7 @@
#ifndef MM1_VIEWS_GAME_MESSAGES_H
#define MM1_VIEWS_GAME_MESSAGES_H
+#include "common/str-array.h"
#include "mm/mm1/views/text_view.h"
namespace MM {
@@ -29,12 +30,14 @@ namespace MM1 {
namespace Views {
class GameMessages : public TextView {
+private:
+ Common::StringArray _lines;
public:
- GameMessages(UIElement *owner) : TextView("GameMessages", owner) {}
+ GameMessages(UIElement *owner);
virtual ~GameMessages() {}
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgInfo(const InfoMessage &msg) override;
};
} // namespace Views
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 83baf636198..8560ef605d8 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
mm1/data/char.o \
mm1/data/game_state.o \
mm1/data/roster.o \
+ mm1/game/search.o \
mm1/game/view_base.o \
mm1/gfx/dta.o \
mm1/gfx/gfx.o \
Commit: 88cb46734cd6fe2b07e40ae61a49af93c405b0c5
https://github.com/scummvm/scummvm/commit/88cb46734cd6fe2b07e40ae61a49af93c405b0c5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Split off messages into their own file, improve Info message
Changed paths:
A engines/mm/mm1/messages.cpp
A engines/mm/mm1/messages.h
engines/mm/mm1/events.h
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/game_messages.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 0d6922f948d..cc404de1909 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -23,51 +23,15 @@
#define MM1_EVENTS_H
#include "common/array.h"
-#include "common/events.h"
#include "common/stack.h"
-#include "common/str-array.h"
#include "graphics/screen.h"
-#include "mm/mm1/meta_engine.h"
+#include "mm/mm1/messages.h"
namespace MM {
namespace MM1 {
class Events;
-struct Message {};
-struct FocusMessage : public Message {};
-struct UnfocusMessage : public Message {};
-struct ActionMessage : public Message {
- KeybindingAction _action;
- ActionMessage() : Message(), _action(KEYBIND_NONE) {}
- ActionMessage(KeybindingAction action) : Message(),
- _action(action) {}
-};
-
-struct KeypressMessage : public Message, public Common::KeyState {
- KeypressMessage() : Message() {}
- KeypressMessage(const Common::KeyState &ks) :
- Message(), Common::KeyState(ks) {}
-};
-
-struct GameMessage : public Message {
- Common::String _name;
- GameMessage() : Message() {}
- GameMessage(const Common::String &name) : Message(),
- _name(name) {}
-};
-
-struct InfoMessage : public Message {
- Common::StringArray _lines;
- InfoMessage() : Message() {}
- InfoMessage(const Common::String &str) : Message() {
- _lines.push_back("");
- _lines.push_back(str);
- }
- InfoMessage(const Common::StringArray &lines) :
- Message(), _lines(lines) {}
-};
-
class UIElement {
friend class Events;
protected:
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
new file mode 100644
index 00000000000..4a92627c2e0
--- /dev/null
+++ b/engines/mm/mm1/messages.cpp
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/messages.h"
+
+namespace MM {
+namespace MM1 {
+
+InfoMessage::InfoMessage() : Message(), _callbackFn(nullptr) {}
+
+InfoMessage::InfoMessage(const Common::String &str) :
+ Message(), _callbackFn(nullptr) {
+ _lines.push_back(str);
+}
+
+InfoMessage::InfoMessage(int x, int y, const Common::String &str,
+ InfoKeyCallback callbackFn) :
+ Message(), _callbackFn(callbackFn) {
+ _lines.push_back(Line(x, y, str));
+}
+
+InfoMessage::InfoMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2,
+ InfoKeyCallback callbackFn) :
+ Message(), _callbackFn(callbackFn) {
+ _lines.push_back(Line(x1, y1, str1));
+ _lines.push_back(Line(x2, y2, str2));
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
new file mode 100644
index 00000000000..a308b490a45
--- /dev/null
+++ b/engines/mm/mm1/messages.h
@@ -0,0 +1,82 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MESSAGES_H
+#define MM1_MESSAGES_H
+
+#include "common/array.h"
+#include "common/events.h"
+#include "common/str.h"
+#include "mm/mm1/meta_engine.h"
+
+namespace MM {
+namespace MM1 {
+
+struct Message {};
+struct FocusMessage : public Message {};
+struct UnfocusMessage : public Message {};
+struct ActionMessage : public Message {
+ KeybindingAction _action;
+ ActionMessage() : Message(), _action(KEYBIND_NONE) {}
+ ActionMessage(KeybindingAction action) : Message(),
+ _action(action) {}
+};
+
+struct KeypressMessage : public Message, public Common::KeyState {
+ KeypressMessage() : Message() {}
+ KeypressMessage(const Common::KeyState &ks) :
+ Message(), Common::KeyState(ks) {}
+};
+
+struct GameMessage : public Message {
+ Common::String _name;
+ GameMessage() : Message() {}
+ GameMessage(const Common::String &name) : Message(),
+ _name(name) {}
+};
+
+typedef bool (*InfoKeyCallback)(const Common::KeyState &keyState);
+struct InfoMessage : public Message {
+ struct Line : public Common::Point {
+ Common::String _text;
+
+ Line() {}
+ Line(const Common::String &text) :
+ Common::Point(), _text(text) {}
+ Line(int x, int y, const Common::String &text) :
+ Common::Point(x, y), _text(text) {}
+ };
+ Common::Array<Line> _lines;
+ InfoKeyCallback _callbackFn;
+
+ InfoMessage();
+ InfoMessage(const Common::String &str);
+ InfoMessage(int x, int y, const Common::String &str,
+ InfoKeyCallback callbackFn = nullptr);
+ InfoMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2,
+ InfoKeyCallback callbackFn = nullptr);
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 8baf5a7add0..e59d8f6542b 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -29,15 +29,25 @@ namespace Views {
GameMessages::GameMessages(UIElement *owner) :
TextView("GameMessages", owner) {
- _bounds = getLineBounds(20, 24);
+ _bounds = getLineBounds(21, 24);
}
void GameMessages::draw() {
clearSurface();
- for (uint i = 0; i < MIN(_lines.size(), 4U); ++i)
- writeString(0, i, _lines[i]);
- _lines.clear();
+ if (!_lines.empty()) {
+ if (_lines[0].y == 0) {
+ // No co-ordinates provided, just display
+ for (uint i = 0; i < MIN(_lines.size(), 4U); ++i)
+ writeString(0, i, _lines[i]._text);
+ } else {
+ // Write text at suggested co-ordinates
+ for (uint i = 0; i < MIN(_lines.size(), 4U); ++i)
+ writeString(_lines[i].x, _lines[i].y, _lines[i]._text);
+ }
+
+ _lines.clear();
+ }
}
bool GameMessages::msgInfo(const InfoMessage &msg) {
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
index 73b432685c3..52c75d62828 100644
--- a/engines/mm/mm1/views/game_messages.h
+++ b/engines/mm/mm1/views/game_messages.h
@@ -22,7 +22,7 @@
#ifndef MM1_VIEWS_GAME_MESSAGES_H
#define MM1_VIEWS_GAME_MESSAGES_H
-#include "common/str-array.h"
+#include "mm/mm1/messages.h"
#include "mm/mm1/views/text_view.h"
namespace MM {
@@ -31,7 +31,7 @@ namespace Views {
class GameMessages : public TextView {
private:
- Common::StringArray _lines;
+ Common::Array<InfoMessage::Line> _lines;
public:
GameMessages(UIElement *owner);
virtual ~GameMessages() {}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 8560ef605d8..f7206a8d666 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS := \
mm1/console.o \
mm1/events.o \
mm1/globals.o \
+ mm1/messages.o \
mm1/meta_engine.o \
mm1/mm1.o \
mm1/sound.o \
Commit: ae5e45b17b579f7dc5126d179df92f19092069aa
https://github.com/scummvm/scummvm/commit/ae5e45b17b579f7dc5126d179df92f19092069aa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Implement shop signs message display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/sound.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game_messages.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index af4ac2d5ab5..ac25e0b0152 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -421,11 +421,12 @@ stats:
255: "(USELESS ITEM)"
maps:
map00:
+ sign: "A SIGN ABOVE THE DOOR READS: "
+ eulards: """EULARDS FINE FOODS"""
+ blacksmith: """B AND B BLACKSMITHING"""
+ inn: """THE INN OF SORPIGAL"""
+
c9d3: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
- ca28: """EULARDS FINE FOODS"""
- ca3d: """B AND B BLACKSMITHING"""
- ca53: """THE INN OF SORPIGAL"""
- ca0a: "A SIGN ABOVE THE DOOR READS: "
ca69: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
cade: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
cdcb: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index ba2dfc8f4de..8814387e51c 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -162,7 +162,7 @@ void ViewBase::forward(KeybindingAction action) {
if (map.dataByte(30 + offset) == 4 &&
!g_globals->_spells._s.walk_on_water) {
- Sound::sound(SOUND_OBSTRUCTED);
+ Sound::sound(SOUND_1);
_dialogMessage = STRING["movement.obstructed.cant_swim"];
redraw();
return;
@@ -193,12 +193,12 @@ void ViewBase::backwards() {
if (!g_globals->_intangible) {
if (maps._currentWalls & maps._backwardsMask) {
- Sound::sound(SOUND_OBSTRUCTED);
+ Sound::sound(SOUND_1);
map.checkPartyDead();
return;
}
if (maps._currentState & 0x55 & maps._backwardsMask) {
- Sound::sound(SOUND_OBSTRUCTED);
+ Sound::sound(SOUND_1);
map.checkPartyDead();
return;
}
@@ -230,7 +230,7 @@ Common::Point ViewBase::getMoveDelta(byte mask) const {
void ViewBase::obstructed(byte mask) {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
- Sound::sound(SOUND_OBSTRUCTED);
+ Sound::sound(SOUND_1);
int index = 32;
if (!(maps._currentWalls & mask & 0x55))
@@ -245,7 +245,7 @@ void ViewBase::obstructed(byte mask) {
void ViewBase::barrier() {
_dialogMessage = STRING["movement.obstructed.barrier"];
- Sound::sound(SOUND_OBSTRUCTED);
+ Sound::sound(SOUND_1);
}
void ViewBase::bash() {
@@ -266,7 +266,7 @@ void ViewBase::bash() {
if (map.dataByte(index) != 1) {
forward(KEYBIND_FORWARDS);
} else {
- Sound::sound(SOUND_OBSTRUCTED);
+ Sound::sound(SOUND_1);
uint might = g_engine->getRandomNumber(100);
for (uint i = 0; i < g_globals->_party.size(); ++i)
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index dffba001415..7fd6cbafb53 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -20,8 +20,10 @@
*/
#include "mm/mm1/maps/map00.h"
+#include "mm/mm1/maps/maps.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -51,7 +53,33 @@ void Map00::special() {
}
void Map00::special00() { warning("special00"); }
-void Map00::special01() { warning("special01"); }
+
+void Map00::special01() {
+ Maps &maps = g_globals->_maps;
+ Sound::sound(SOUND_2);
+
+ Common::String line2;
+ int x = 5;
+
+ switch (maps._forwardMask) {
+ case DIRMASK_E:
+ line2 = STRING["maps.map00.eulards"];
+ x = 6;
+ break;
+ case DIRMASK_W:
+ line2 = STRING["maps.map00.blacksmith"];
+ break;
+ default:
+ line2 = STRING["maps.map00.inn"];
+ break;
+ }
+
+ g_events->msgInfo(InfoMessage(
+ 2, 0, STRING["maps.map00.sign"],
+ x, 1, line2
+ ));
+}
+
void Map00::special02() { warning("special02"); }
void Map00::special03() { warning("special03"); }
void Map00::special04() { warning("special04"); }
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index a308b490a45..eaaf503ba2b 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -60,7 +60,7 @@ struct InfoMessage : public Message {
Line() {}
Line(const Common::String &text) :
- Common::Point(), _text(text) {}
+ Common::Point(-1, -1), _text(text) {}
Line(int x, int y, const Common::String &text) :
Common::Point(x, y), _text(text) {}
};
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
index b8b22295741..3b0340a4643 100644
--- a/engines/mm/mm1/sound.h
+++ b/engines/mm/mm1/sound.h
@@ -25,7 +25,7 @@
namespace MM {
namespace MM1 {
-enum SoundId { SOUND_OBSTRUCTED = 1, SOUND_BASH = 2 };
+enum SoundId { SOUND_1 = 1, SOUND_2 = 2 };
class Sound {
public:
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index fb86ded40cc..a43f789ca38 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -44,9 +44,7 @@ bool Game::msgUnfocus(const UnfocusMessage &msg) {
}
void Game::draw() {
- if (_needsRedraw)
- clearSurface();
- TextView::draw();
+ clearSurface();
}
bool Game::msgAction(const ActionMessage &msg) {
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index e59d8f6542b..ed789ceea01 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -36,7 +36,7 @@ void GameMessages::draw() {
clearSurface();
if (!_lines.empty()) {
- if (_lines[0].y == 0) {
+ if (_lines[0].y == -1) {
// No co-ordinates provided, just display
for (uint i = 0; i < MIN(_lines.size(), 4U); ++i)
writeString(0, i, _lines[i]._text);
Commit: f2346f3ff055135c2bdc6736196098b68d3831de
https://github.com/scummvm/scummvm/commit/f2346f3ff055135c2bdc6736196098b68d3831de
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Refactor maps collection to be in maps.cpp
Changed paths:
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map00.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/game_view.cpp
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index d0807b8e6b9..dfbebaeb9ac 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -29,9 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
-Map::Map(Maps *owner, const Common::String &name, uint16 id) :
- _name(name), _id(id) {
- _mapId = owner->addMap(this);
+Map::Map(uint index, const Common::String &name, uint16 id) :
+ _mapIndex(index), _name(name), _id(id) {
Common::fill((byte *)&_walls[0], (byte *)&_walls[MAP_SIZE], 0);
Common::fill(&_states[0], (byte *)&_states[MAP_SIZE], 0);
}
@@ -46,7 +45,7 @@ void Map::loadMazeData() {
if (!f.open("mazedata.dta"))
error("Could not open mazedata.dta");
- f.seek(512 * _mapId);
+ f.seek(512 * _mapIndex);
f.read((byte *)_walls, MAP_SIZE);
f.read(_states, MAP_SIZE);
f.close();
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index c2a321cd751..1c81bbb1641 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -48,7 +48,7 @@ class Map {
protected:
Common::String _name;
uint16 _id;
- uint _mapId;
+ uint _mapIndex;
Common::Array<byte> _data;
private:
/**
@@ -64,7 +64,7 @@ public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
public:
- Map(Maps *owner, const Common::String &name, uint16 id);
+ Map(uint index, const Common::String &name, uint16 id);
virtual ~Map() {}
/**
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 7fd6cbafb53..d81454b2b7b 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -30,14 +30,12 @@ namespace MM1 {
namespace Maps {
void Map00::special() {
- Maps &maps = g_globals->_maps;
-
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
- if (maps._mapOffset == _data[51 + i]) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (maps._forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[75 + i]) {
// TODO: Some extra message code
(this->*SPECIAL_FN[i])();
} else {
@@ -48,20 +46,19 @@ void Map00::special() {
}
// All other cells on the map are encounters
- maps.clearSpecial();
+ g_maps->clearSpecial();
g_events->addView("Encounter");
}
void Map00::special00() { warning("special00"); }
void Map00::special01() {
- Maps &maps = g_globals->_maps;
Sound::sound(SOUND_2);
Common::String line2;
int x = 5;
- switch (maps._forwardMask) {
+ switch (g_maps->_forwardMask) {
case DIRMASK_E:
line2 = STRING["maps.map00.eulards"];
x = 6;
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index a8420f4ccef..3e3c18f7c7a 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -83,7 +83,7 @@ private:
&Map00::special23
};
public:
- Map00(Maps *owner) : Map(owner, "sorpigal", 0x604) {}
+ Map00() : Map(0, "sorpigal", 0x604) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 2ee2e77fdae..e944f2ad9bf 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -21,16 +21,83 @@
#include "common/endian.h"
#include "common/stream.h"
-#include "mm/mm1/maps/maps.h"
+#include "common/system.h"
+#include "mm/mm1/events.h"
#include "mm/mm1/gfx/dta.h"
#include "mm/mm1/gfx/screen_decoder.h"
-#include "mm/mm1/events.h"
-#include "common/system.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/maps/map00.h"
namespace MM {
namespace MM1 {
namespace Maps {
+Maps *g_maps;
+
+/** PLACEHOLDER MAPS **/
+#define PLACEHOLDER(SUFFIX, INDEX, NAME, ID) \
+ class Map##SUFFIX : public Map { \
+ public: \
+ Map##SUFFIX() : Map(INDEX, NAME, ID) {} \
+ void special() override {} \
+ }
+
+PLACEHOLDER(01, 1, "portsmit", 0xC03);
+PLACEHOLDER(02, 2, "algary", 0x203);
+PLACEHOLDER(03, 3, "dusk", 0x802);
+PLACEHOLDER(04, 4, "erliquin", 0x0B1A);
+PLACEHOLDER(05, 5, "cave1", 0x0A11);
+PLACEHOLDER(06, 6, "cave2", 0x1);
+PLACEHOLDER(07, 7, "cave3", 0xC01);
+PLACEHOLDER(08, 8, "cave4", 0x202);
+PLACEHOLDER(09, 9, "cave5", 0x5);
+PLACEHOLDER(10, 10, "cave6", 0x51B);
+PLACEHOLDER(11, 11, "cave7", 0x212);
+PLACEHOLDER(12, 12, "cave8", 0x601);
+PLACEHOLDER(13, 13, "cave9", 0xA00);
+PLACEHOLDER(14, 14, "areaa1", 0xF01);
+PLACEHOLDER(15, 15, "areaa2", 0x502);
+PLACEHOLDER(16, 16, "areaa3", 0xB02);
+PLACEHOLDER(17, 17, "areaa4", 0x103);
+PLACEHOLDER(18, 18, "areab1", 0xA00);
+PLACEHOLDER(19, 19, "areab2", 0x703);
+PLACEHOLDER(20, 20, "areab3", 0x101);
+PLACEHOLDER(21, 21, "areab4", 0xD03);
+PLACEHOLDER(22, 22, "areac1", 0x304);
+PLACEHOLDER(23, 23, "areac2", 0xA11);
+PLACEHOLDER(24, 24, "areac3", 0x904);
+PLACEHOLDER(25, 25, "areac4", 0xF04);
+PLACEHOLDER(26, 26, "aread1", 0x505);
+PLACEHOLDER(27, 27, "aread2", 0xB05);
+PLACEHOLDER(28, 28, "aread3", 0x106);
+PLACEHOLDER(29, 29, "aread4", 0x801);
+PLACEHOLDER(30, 30, "areae1", 0x112);
+PLACEHOLDER(31, 31, "areae2", 0x706);
+PLACEHOLDER(32, 32, "areae3", 0xB1A);
+PLACEHOLDER(33, 33, "areae4", 0x11B);
+PLACEHOLDER(34, 34, "doom", 0x706);
+PLACEHOLDER(35, 35, "blackrn", 0xF08);
+PLACEHOLDER(36, 36, "blackrs", 0x508);
+PLACEHOLDER(37, 37, "qvl1", 0xF03);
+PLACEHOLDER(38, 38, "qvl2", 0x703);
+PLACEHOLDER(39, 39, "rwl1", 0xF02);
+PLACEHOLDER(40, 40, "rwl2", 0x702);
+PLACEHOLDER(41, 41, "enf1", 0xF04);
+PLACEHOLDER(42, 42, "enf2", 0x704);
+PLACEHOLDER(43, 43, "whitew", 0xA11);
+PLACEHOLDER(44, 44, "dragad", 0x107);
+PLACEHOLDER(45, 45, "udrag1", 0xF05);
+PLACEHOLDER(46, 46, "udrag2", 0xA00);
+PLACEHOLDER(47, 47, "udrag3", 0x705);
+PLACEHOLDER(48, 48, "demon", 0x412);
+PLACEHOLDER(49, 49, "alamar", 0xB07);
+PLACEHOLDER(50, 50, "pp1", 0xF01);
+PLACEHOLDER(51, 51, "pp2", 0x701);
+PLACEHOLDER(52, 52, "pp3", 0xE00);
+PLACEHOLDER(53, 53, "pp4", 0x201);
+PLACEHOLDER(54, 54, "astral", 0xB1A);
+#undef PLACEHOLDER
+
static const byte LOOKUPS_START[4] = { 0, 0, 14, 34 };
static const byte COLOR_OFFSET[55] = {
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
@@ -62,22 +129,71 @@ static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
};
-Maps::Maps() :
- _map00(this), _map01(this), _map02(this), _map03(this),
- _map04(this), _map05(this), _map06(this), _map07(this),
- _map08(this), _map09(this), _map10(this), _map11(this),
- _map12(this), _map13(this), _map14(this), _map15(this),
- _map16(this), _map17(this), _map18(this), _map19(this),
- _map20(this), _map21(this), _map22(this), _map23(this),
- _map24(this), _map25(this), _map26(this), _map27(this),
- _map28(this), _map29(this), _map30(this), _map31(this),
- _map32(this), _map33(this), _map34(this), _map35(this),
- _map36(this), _map37(this), _map38(this), _map39(this),
- _map40(this), _map41(this), _map42(this), _map43(this),
- _map44(this), _map45(this), _map46(this), _map47(this),
- _map48(this), _map49(this), _map50(this), _map51(this),
- _map52(this), _map53(this), _map54(this) {
+Maps::Maps() {
+ g_maps = this;
Common::fill(&_data1[0], &_data1[32], 0);
+
+ _maps.push_back(new Map00());
+ _maps.push_back(new Map01());
+ _maps.push_back(new Map02());
+ _maps.push_back(new Map03());
+ _maps.push_back(new Map04());
+ _maps.push_back(new Map05());
+ _maps.push_back(new Map06());
+ _maps.push_back(new Map07());
+ _maps.push_back(new Map08());
+ _maps.push_back(new Map09());
+ _maps.push_back(new Map10());
+ _maps.push_back(new Map11());
+ _maps.push_back(new Map12());
+ _maps.push_back(new Map13());
+ _maps.push_back(new Map14());
+ _maps.push_back(new Map15());
+ _maps.push_back(new Map16());
+ _maps.push_back(new Map17());
+ _maps.push_back(new Map18());
+ _maps.push_back(new Map19());
+ _maps.push_back(new Map20());
+ _maps.push_back(new Map21());
+ _maps.push_back(new Map22());
+ _maps.push_back(new Map23());
+ _maps.push_back(new Map24());
+ _maps.push_back(new Map25());
+ _maps.push_back(new Map26());
+ _maps.push_back(new Map27());
+ _maps.push_back(new Map28());
+ _maps.push_back(new Map29());
+ _maps.push_back(new Map30());
+ _maps.push_back(new Map31());
+ _maps.push_back(new Map32());
+ _maps.push_back(new Map33());
+ _maps.push_back(new Map34());
+ _maps.push_back(new Map35());
+ _maps.push_back(new Map36());
+ _maps.push_back(new Map37());
+ _maps.push_back(new Map38());
+ _maps.push_back(new Map39());
+ _maps.push_back(new Map40());
+ _maps.push_back(new Map41());
+ _maps.push_back(new Map42());
+ _maps.push_back(new Map43());
+ _maps.push_back(new Map44());
+ _maps.push_back(new Map45());
+ _maps.push_back(new Map46());
+ _maps.push_back(new Map47());
+ _maps.push_back(new Map48());
+ _maps.push_back(new Map49());
+ _maps.push_back(new Map50());
+ _maps.push_back(new Map51());
+ _maps.push_back(new Map52());
+ _maps.push_back(new Map53());
+ _maps.push_back(new Map54());
+}
+
+Maps::~Maps() {
+ for (uint i = 0; i < _maps.size(); ++i)
+ delete _maps[i];
+ g_maps = nullptr;
}
void Maps::load(uint mapId) {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 6eb0105585f..b77b1666ffd 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -25,7 +25,7 @@
#include "common/array.h"
#include "common/rect.h"
#include "graphics/managed_surface.h"
-#include "mm/mm1/maps/map00.h"
+#include "mm/mm1/maps/map.h"
namespace MM {
namespace MM1 {
@@ -41,70 +41,6 @@ enum DirMask {
DIRMASK_S = 0xC, DIRMASK_W = 3
};
-/** PLACEHOLDER MAPS **/
-#define PLACEHOLDER(INDEX, NAME, ID) \
- class Map##INDEX : public Map { \
- public: \
- Map##INDEX(Maps *owner) : Map(owner, NAME, ID) {} \
- void special() override {} \
- }
-
-PLACEHOLDER(01, "portsmit", 0xC03);
-PLACEHOLDER(02, "algary", 0x203);
-PLACEHOLDER(03, "dusk", 0x802);
-PLACEHOLDER(04, "erliquin", 0x0B1A);
-PLACEHOLDER(05, "cave1", 0x0A11);
-PLACEHOLDER(06, "cave2", 0x1);
-PLACEHOLDER(07, "cave3", 0xC01);
-PLACEHOLDER(08, "cave4", 0x202);
-PLACEHOLDER(09, "cave5", 0x5);
-PLACEHOLDER(10, "cave6", 0x51B);
-PLACEHOLDER(11, "cave7", 0x212);
-PLACEHOLDER(12, "cave8", 0x601);
-PLACEHOLDER(13, "cave9", 0xA00);
-PLACEHOLDER(14, "areaa1", 0xF01);
-PLACEHOLDER(15, "areaa2", 0x502);
-PLACEHOLDER(16, "areaa3", 0xB02);
-PLACEHOLDER(17, "areaa4", 0x103);
-PLACEHOLDER(18, "areab1", 0xA00);
-PLACEHOLDER(19, "areab2", 0x703);
-PLACEHOLDER(20, "areab3", 0x101);
-PLACEHOLDER(21, "areab4", 0xD03);
-PLACEHOLDER(22, "areac1", 0x304);
-PLACEHOLDER(23, "areac2", 0xA11);
-PLACEHOLDER(24, "areac3", 0x904);
-PLACEHOLDER(25, "areac4", 0xF04);
-PLACEHOLDER(26, "aread1", 0x505);
-PLACEHOLDER(27, "aread2", 0xB05);
-PLACEHOLDER(28, "aread3", 0x106);
-PLACEHOLDER(29, "aread4", 0x801);
-PLACEHOLDER(30, "areae1", 0x112);
-PLACEHOLDER(31, "areae2", 0x706);
-PLACEHOLDER(32, "areae3", 0xB1A);
-PLACEHOLDER(33, "areae4", 0x11B);
-PLACEHOLDER(34, "doom", 0x706);
-PLACEHOLDER(35, "blackrn", 0xF08);
-PLACEHOLDER(36, "blackrs", 0x508);
-PLACEHOLDER(37, "qvl1", 0xF03);
-PLACEHOLDER(38, "qvl2", 0x703);
-PLACEHOLDER(39, "rwl1", 0xF02);
-PLACEHOLDER(40, "rwl2", 0x702);
-PLACEHOLDER(41, "enf1", 0xF04);
-PLACEHOLDER(42, "enf2", 0x704);
-PLACEHOLDER(43, "whitew", 0xA11);
-PLACEHOLDER(44, "dragad", 0x107);
-PLACEHOLDER(45, "udrag1", 0xF05);
-PLACEHOLDER(46, "udrag2", 0xA00);
-PLACEHOLDER(47, "udrag3", 0x705);
-PLACEHOLDER(48, "demon", 0x412);
-PLACEHOLDER(49, "alamar", 0xB07);
-PLACEHOLDER(50, "pp1", 0xF01);
-PLACEHOLDER(51, "pp2", 0x701);
-PLACEHOLDER(52, "pp3", 0xE00);
-PLACEHOLDER(53, "pp4", 0x201);
-PLACEHOLDER(54, "astral", 0xB1A);
-#undef PLACEHOLDER
-
/**
* Container for all the game maps
*/
@@ -112,71 +48,7 @@ class Maps {
friend class Map;
private:
Common::Array<Map *> _maps;
-private:
- Map00 _map00;
- Map01 _map01;
- Map02 _map02;
- Map03 _map03;
- Map04 _map04;
- Map05 _map05;
- Map06 _map06;
- Map07 _map07;
- Map08 _map08;
- Map09 _map09;
- Map10 _map10;
- Map11 _map11;
- Map12 _map12;
- Map13 _map13;
- Map14 _map14;
- Map15 _map15;
- Map16 _map16;
- Map17 _map17;
- Map18 _map18;
- Map19 _map19;
- Map20 _map20;
- Map21 _map21;
- Map22 _map22;
- Map23 _map23;
- Map24 _map24;
- Map25 _map25;
- Map26 _map26;
- Map27 _map27;
- Map28 _map28;
- Map29 _map29;
- Map30 _map30;
- Map31 _map31;
- Map32 _map32;
- Map33 _map33;
- Map34 _map34;
- Map35 _map35;
- Map36 _map36;
- Map37 _map37;
- Map38 _map38;
- Map39 _map39;
- Map40 _map40;
- Map41 _map41;
- Map42 _map42;
- Map43 _map43;
- Map44 _map44;
- Map45 _map45;
- Map46 _map46;
- Map47 _map47;
- Map48 _map48;
- Map49 _map49;
- Map50 _map50;
- Map51 _map51;
- Map52 _map52;
- Map53 _map53;
- Map54 _map54;
private:
- /**
- * Adds map class
- */
- uint addMap(Map *map) {
- _maps.push_back(map);
- return _maps.size() - 1;
- }
-
/**
* Gets the index of a map given the id values
*/
@@ -226,6 +98,7 @@ public:
byte _loadFlag = 0;
public:
Maps();
+ ~Maps();
/**
* Load a map
@@ -275,6 +148,8 @@ public:
void clearSpecial();
};
+extern Maps *g_maps;
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index c75852976ec..c08c6850f44 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views/game_view.h"
+#include "mm/mm1/maps/maps.h"
#include "mm/mm1/globals.h"
namespace MM {
Commit: 6ab8c299f981d098a0fc62c50cb7489f8c10e376
https://github.com/scummvm/scummvm/commit/6ab8c299f981d098a0fc62c50cb7489f8c10e376
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Implement support for Y/N messages
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/messages.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/game_messages.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ac25e0b0152..74019f94e5f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -425,11 +425,11 @@ maps:
eulards: """EULARDS FINE FOODS"""
blacksmith: """B AND B BLACKSMITHING"""
inn: """THE INN OF SORPIGAL"""
+ passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
c9d3: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
ca69: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
- cade: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
- cdcb: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ food: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
cb56: "STEP UP TO THE BAR (Y/N)?"
cb70: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
cbc8: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 159265b928d..44991b1b2da 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -56,6 +56,7 @@ void Events::runGame() {
for (uint i = 0; i < 6; ++i)
g_globals->_party.push_back(g_globals->_roster[i]);
g_globals->_maps.loadTown(Maps::SORPIGAL);
+ msgGame(GameMessage("UPDATE"));
//addView("Title");
Common::Event e;
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 8814387e51c..238d128897a 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -101,7 +101,6 @@ bool ViewBase::msgAction(const ActionMessage &msg) {
}
bool ViewBase::msgFocus(const FocusMessage &msg) {
- update();
return false;
}
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 1c81bbb1641..b61874547a3 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -44,6 +44,8 @@ enum CellState {
CELL_SPECIAL = 0x80, CELL_DARK = 0x20
};
+class Maps;
+
class Map {
protected:
Common::String _name;
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index d81454b2b7b..13b8723043c 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -78,8 +78,27 @@ void Map00::special01() {
}
void Map00::special02() { warning("special02"); }
-void Map00::special03() { warning("special03"); }
-void Map00::special04() { warning("special04"); }
+
+void Map00::special03() {
+ /*
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ STRING["maps.map00.food"],
+ []() {
+
+ }
+ ));
+ */
+}
+
+void Map00::special04() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ STRING["maps.map00.passage_outside"],
+ []() { g_maps->select(0xa11, 2); }
+ ));
+}
+
void Map00::special05() { warning("special05"); }
void Map00::special06() { warning("special06"); }
void Map00::special07() { warning("special07"); }
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index e944f2ad9bf..43a5c7531cd 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -40,6 +40,10 @@ Maps *g_maps;
public: \
Map##SUFFIX() : Map(INDEX, NAME, ID) {} \
void special() override {} \
+ void load() override { \
+ Map::load(); \
+ warning("TODO: Map not implemented yet"); \
+ } \
}
PLACEHOLDER(01, 1, "portsmit", 0xC03);
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
index 4a92627c2e0..265e1e7c537 100644
--- a/engines/mm/mm1/messages.cpp
+++ b/engines/mm/mm1/messages.cpp
@@ -24,23 +24,24 @@
namespace MM {
namespace MM1 {
-InfoMessage::InfoMessage() : Message(), _callbackFn(nullptr) {}
+InfoMessage::InfoMessage() : Message(), _ynCallback(nullptr) {}
-InfoMessage::InfoMessage(const Common::String &str) :
- Message(), _callbackFn(nullptr) {
+InfoMessage::InfoMessage(const Common::String &str,
+ YNCallback ynCallback) :
+ Message(), _ynCallback(ynCallback) {
_lines.push_back(str);
}
InfoMessage::InfoMessage(int x, int y, const Common::String &str,
- InfoKeyCallback callbackFn) :
- Message(), _callbackFn(callbackFn) {
+ YNCallback ynCallback) :
+ Message(), _ynCallback(ynCallback) {
_lines.push_back(Line(x, y, str));
}
InfoMessage::InfoMessage(int x1, int y1, const Common::String &str1,
int x2, int y2, const Common::String &str2,
- InfoKeyCallback callbackFn) :
- Message(), _callbackFn(callbackFn) {
+ YNCallback ynCallback) :
+ Message(), _ynCallback(ynCallback) {
_lines.push_back(Line(x1, y1, str1));
_lines.push_back(Line(x2, y2, str2));
}
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index eaaf503ba2b..b25f4289d10 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -53,7 +53,7 @@ struct GameMessage : public Message {
_name(name) {}
};
-typedef bool (*InfoKeyCallback)(const Common::KeyState &keyState);
+typedef void (*YNCallback)();
struct InfoMessage : public Message {
struct Line : public Common::Point {
Common::String _text;
@@ -65,15 +65,16 @@ struct InfoMessage : public Message {
Common::Point(x, y), _text(text) {}
};
Common::Array<Line> _lines;
- InfoKeyCallback _callbackFn;
+ YNCallback _ynCallback;
InfoMessage();
- InfoMessage(const Common::String &str);
+ InfoMessage(const Common::String &str,
+ YNCallback ynCallback = nullptr);
InfoMessage(int x, int y, const Common::String &str,
- InfoKeyCallback callbackFn = nullptr);
+ YNCallback ynCallback = nullptr);
InfoMessage(int x1, int y1, const Common::String &str1,
int x2, int y2, const Common::String &str2,
- InfoKeyCallback callbackFn = nullptr);
+ YNCallback ynCallback = nullptr);
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index ed789ceea01..99c2de5eb3e 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -51,11 +51,36 @@ void GameMessages::draw() {
}
bool GameMessages::msgInfo(const InfoMessage &msg) {
+ if (msg._ynCallback) {
+ // Do a first draw to show 3d view at new position
+ g_events->redraw();
+ g_events->drawElements();
+
+ addView(this);
+ }
+
_lines = msg._lines;
+ _ynCallback = msg._ynCallback;
+
redraw();
return true;
}
+bool GameMessages::msgKeypress(const KeypressMessage &msg) {
+ if (g_events->focusedView() == this) {
+ if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ } else if (msg.keycode == Common::KEYCODE_y) {
+ close();
+ _ynCallback();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
index 52c75d62828..506c1a5c8e5 100644
--- a/engines/mm/mm1/views/game_messages.h
+++ b/engines/mm/mm1/views/game_messages.h
@@ -32,12 +32,14 @@ namespace Views {
class GameMessages : public TextView {
private:
Common::Array<InfoMessage::Line> _lines;
+ YNCallback _ynCallback = nullptr;
public:
GameMessages(UIElement *owner);
virtual ~GameMessages() {}
void draw() override;
bool msgInfo(const InfoMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace Views
Commit: a815a3cbaaac4afd561a9b93c901ad93aeadcec3
https://github.com/scummvm/scummvm/commit/a815a3cbaaac4afd561a9b93c901ad93aeadcec3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Fixes for leaving Sorpigal
Changed paths:
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 13b8723043c..7b16b44ff2f 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -95,7 +95,10 @@ void Map00::special04() {
Sound::sound(SOUND_2);
g_events->msgInfo(InfoMessage(
STRING["maps.map00.passage_outside"],
- []() { g_maps->select(0xa11, 2); }
+ []() {
+ g_maps->_mapPos = Common::Point(10, 10);
+ g_maps->changeMap(0xa11, 2);
+ }
));
}
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 43a5c7531cd..b222427f0dd 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -289,7 +289,7 @@ void Maps::town4setup() {
}
uint Maps::getIndex(uint16 id, byte section) {
- uint idx = LOOKUPS_START[section / 2];
+ uint idx = LOOKUPS_START[section];
// Find map by Id
for (; id != _maps[idx]->getId(); ++idx) {
@@ -407,9 +407,15 @@ void Maps::step(const Common::Point &delta) {
return;
}
+ changeMap(id, section);
+}
+
+void Maps::changeMap(uint16 id, byte section) {
// At this point, a new map is being entered
select(id, section);
loadTiles();
+
+ g_events->msgGame(GameMessage("UPDATE"));
}
void Maps::clearSpecial() {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index b77b1666ffd..aff82a37064 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -140,6 +140,12 @@ public:
*/
void step(const Common::Point &delta);
+ /**
+ * Called when a map is left to load a new one
+ * and trigger the 3d view to update
+ */
+ void changeMap(uint16 id, byte section);
+
/**
* Disables the special state of the current cell
* This is primiarily used for disabling cells
Commit: 1c7c034ae5b422379e7ea7a1c2d69a3baaa7ae4c
https://github.com/scummvm/scummvm/commit/1c7c034ae5b422379e7ea7a1c2d69a3baaa7ae4c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:51+01:00
Commit Message:
MM: MM1: Beginnings of tavern, business display on-screen
Changed paths:
A engines/mm/mm1/views/tavern.cpp
A engines/mm/mm1/views/tavern.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 74019f94e5f..c9201a9d399 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -420,17 +420,23 @@ stats:
254: "EYE OF GORDOS"
255: "(USELESS ITEM)"
maps:
+ businesses:
+ 0: "--TRAINING--"
+ 1: "--MARKET--"
+ 2: "--TEMPLE--"
+ 3: "--BLACKSMITH--"
+ 4: "--TAVERN--"
map00:
sign: "A SIGN ABOVE THE DOOR READS: "
eulards: """EULARDS FINE FOODS"""
blacksmith: """B AND B BLACKSMITHING"""
inn: """THE INN OF SORPIGAL"""
- passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ tavern: "STEP UP TO THE BAR (Y/N)?"
c9d3: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
ca69: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
food: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
- cb56: "STEP UP TO THE BAR (Y/N)?"
+
cb70: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
cbc8: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
@@ -442,6 +448,7 @@ maps:
cdb9: "JAIL. KEEP OUT!"
cdf3: "TRAP DOOR!"
cdfe: ", LEVITATION SAVES YOU!"
+ passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
movement:
obstructed:
0: " SOLID! "
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index cc404de1909..2068f669660 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -131,6 +131,7 @@ public:
MESSAGE(Unfocus);
MESSAGE(Keypress);
MESSAGE(Action);
+ MESSAGE(Business);
MESSAGE(Game);
MESSAGE(Info);
#undef MESSAGE
@@ -195,7 +196,7 @@ public:
}
/**
- * Handles events
+ * Overrides events we want to only go to the focused view
*/
#define MESSAGE(NAME) \
bool msg##NAME(const NAME##Message &e) override { \
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 238d128897a..08a29099928 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -100,6 +100,12 @@ bool ViewBase::msgAction(const ActionMessage &msg) {
return true;
}
+bool ViewBase::msgBusiness(const BusinessMessage &msg) {
+ _businessDisplay = msg._value;
+ draw();
+ return true;
+}
+
bool ViewBase::msgFocus(const FocusMessage &msg) {
return false;
}
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 955f762a68e..07a283cad81 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -37,6 +37,7 @@ class ViewBase : public Views::TextView {
protected:
bool _isDark = false;
Common::String _dialogMessage;
+ int _businessDisplay = -1;
byte _arr2[8];
bool _stepRandom = false;
bool _encounterFlag = false;
@@ -87,6 +88,7 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
+ bool msgBusiness(const BusinessMessage &msg) override;
/**
* Updates game state
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 7b16b44ff2f..12a06bf7ff5 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -102,7 +102,16 @@ void Map00::special04() {
));
}
-void Map00::special05() { warning("special05"); }
+void Map00::special05() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ STRING["maps.map00.tavern"],
+ []() {
+ g_events->addView("TAVERN");
+ }
+ ));
+}
+
void Map00::special06() { warning("special06"); }
void Map00::special07() { warning("special07"); }
void Map00::special08() { warning("special08"); }
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index b25f4289d10..cea5a7e57a2 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -77,6 +77,15 @@ struct InfoMessage : public Message {
YNCallback ynCallback = nullptr);
};
+struct ValueMessage : public Message {
+ int _value;
+
+ ValueMessage() : Message(), _value(0) {}
+ ValueMessage(int value) : Message(),
+ _value(value) {}
+};
+typedef ValueMessage BusinessMessage;
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 5e47dbeb146..6fd4753bf42 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -31,6 +31,7 @@
#include "mm/mm1/views/order.h"
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
+#include "mm/mm1/views/tavern.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
@@ -48,6 +49,7 @@ private:
Views::Order _order;
Views::Protect _protect;
Views::QuickRef _quickRef;
+ Views::Tavern _tavern;
Views::Title _title;
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index c08c6850f44..d6ddf196c23 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -63,6 +63,9 @@ void GameView::draw() {
} else if (_isDark) {
writeString(9, 7, STRING["view.darkness"]);
}
+
+ if (_businessDisplay != -1)
+ drawBusinessName();
}
void GameView::drawScene() {
@@ -198,6 +201,12 @@ void GameView::drawDialogMessage() {
writeString(9, 8, " ");
}
+void GameView::drawBusinessName() {
+ writeString(10, 15, STRING[Common::String::format(
+ "maps.businesses.%d", _businessDisplay)]);
+ _businessDisplay = -1;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index f96bd1de1f9..1b344e443ed 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -49,6 +49,11 @@ private:
* Draws the dialog message
*/
void drawDialogMessage();
+
+ /**
+ * Draws the business name line
+ */
+ void drawBusinessName();
public:
GameView(UIElement *owner);
virtual ~GameView() {}
diff --git a/engines/mm/mm1/views/tavern.cpp b/engines/mm/mm1/views/tavern.cpp
new file mode 100644
index 00000000000..fcb942f5720
--- /dev/null
+++ b/engines/mm/mm1/views/tavern.cpp
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/Tavern.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Tavern::Tavern() : TextView("Tavern") {
+ _bounds = getLineBounds(17, 24);
+}
+
+bool Tavern::msgFocus(const FocusMessage &msg) {
+ g_events->msgBusiness(BusinessMessage(4));
+ return true;
+}
+
+bool Tavern::msgKeypress(const KeypressMessage &msg) {
+ return true;
+}
+
+void Tavern::draw() {
+
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/tavern.h b/engines/mm/mm1/views/tavern.h
new file mode 100644
index 00000000000..d8163a3efa2
--- /dev/null
+++ b/engines/mm/mm1/views/tavern.h
@@ -0,0 +1,45 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_TAVERN_H
+#define MM1_VIEWS_TAVERN_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Tavern : public TextView {
+public:
+ Tavern();
+ virtual ~Tavern() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void draw() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index f7206a8d666..0086632cd76 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -33,6 +33,7 @@ MODULE_OBJS := \
mm1/views/order.o \
mm1/views/protect.o \
mm1/views/quick_ref.o \
+ mm1/views/tavern.o \
mm1/views/title.o \
mm1/views/text_view.o \
mm1/views/view_characters.o \
Commit: e9680b0f50e42224db700bbe0567516b24aad484
https://github.com/scummvm/scummvm/commit/e9680b0f50e42224db700bbe0567516b24aad484
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: Creating separate subfolder for business views
Changed paths:
A engines/mm/mm1/views/businesses/business.cpp
A engines/mm/mm1/views/businesses/business.h
A engines/mm/mm1/views/businesses/tavern.cpp
A engines/mm/mm1/views/businesses/tavern.h
R engines/mm/mm1/views/tavern.cpp
R engines/mm/mm1/views/tavern.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/businesses/business.cpp
new file mode 100644
index 00000000000..567a033f188
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/business.cpp
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/businesses/business.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+Business::Business(const Common::String &name) : TextView(name) {
+ _bounds = getLineBounds(17, 24);
+}
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/business.h b/engines/mm/mm1/views/businesses/business.h
new file mode 100644
index 00000000000..2db1376817c
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/business.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_BUSINESSES_BUSINESS_H
+#define MM1_VIEWS_BUSINESSES_BUSINESS_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+class Business : public TextView {
+public:
+ Business(const Common::String &name);
+ virtual ~Business() {}
+};
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
similarity index 86%
rename from engines/mm/mm1/views/tavern.cpp
rename to engines/mm/mm1/views/businesses/tavern.cpp
index fcb942f5720..8af2aad3a81 100644
--- a/engines/mm/mm1/views/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -19,19 +19,20 @@
*
*/
-#include "mm/mm1/views/Tavern.h"
+#include "mm/mm1/views/businesses/tavern.h"
#include "mm/mm1/globals.h"
namespace MM {
namespace MM1 {
namespace Views {
+namespace Businesses {
-Tavern::Tavern() : TextView("Tavern") {
- _bounds = getLineBounds(17, 24);
+Tavern::Tavern() : Business("Tavern") {
}
bool Tavern::msgFocus(const FocusMessage &msg) {
g_events->msgBusiness(BusinessMessage(4));
+ g_globals->_currCharacter = &g_globals->_party[0];
return true;
}
@@ -43,6 +44,7 @@ void Tavern::draw() {
}
+} // namespace Businesses
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/tavern.h b/engines/mm/mm1/views/businesses/tavern.h
similarity index 83%
rename from engines/mm/mm1/views/tavern.h
rename to engines/mm/mm1/views/businesses/tavern.h
index d8163a3efa2..b3f970eff10 100644
--- a/engines/mm/mm1/views/tavern.h
+++ b/engines/mm/mm1/views/businesses/tavern.h
@@ -19,16 +19,19 @@
*
*/
-#ifndef MM1_VIEWS_TAVERN_H
-#define MM1_VIEWS_TAVERN_H
+#ifndef MM1_VIEWS_BUSINESSES_TAVERN_H
+#define MM1_VIEWS_BUSINESSES_TAVERN_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/businesses/business.h"
namespace MM {
namespace MM1 {
namespace Views {
+namespace Businesses {
-class Tavern : public TextView {
+class Tavern : public Business {
+private:
+ int _val1 = 0;
public:
Tavern();
virtual ~Tavern() {}
@@ -38,6 +41,7 @@ public:
void draw() override;
};
+} // namespace Businesses
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 6fd4753bf42..a81742796c0 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -31,9 +31,9 @@
#include "mm/mm1/views/order.h"
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
-#include "mm/mm1/views/tavern.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/views/businesses/tavern.h"
namespace MM {
namespace MM1 {
@@ -49,10 +49,11 @@ private:
Views::Order _order;
Views::Protect _protect;
Views::QuickRef _quickRef;
- Views::Tavern _tavern;
Views::Title _title;
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
+ Views::Businesses::Tavern _tavern;
+
public:
Dialogs() {}
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 0086632cd76..0d993473ee4 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -21,6 +21,8 @@ MODULE_OBJS := \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
mm1/utils/strings.o \
+ mm1/views/businesses/business.o \
+ mm1/views/businesses/tavern.o \
mm1/views/are_you_ready.o \
mm1/views/create_characters.o \
mm1/views/game.o \
@@ -33,7 +35,6 @@ MODULE_OBJS := \
mm1/views/order.o \
mm1/views/protect.o \
mm1/views/quick_ref.o \
- mm1/views/tavern.o \
mm1/views/title.o \
mm1/views/text_view.o \
mm1/views/view_characters.o \
Commit: bb55556921c3db01efb99c833da5c3e5fc747e88
https://github.com/scummvm/scummvm/commit/bb55556921c3db01efb99c833da5c3e5fc747e88
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: Common business rendering for Tavern
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.h
engines/mm/mm1/views/businesses/business.cpp
engines/mm/mm1/views/businesses/business.h
engines/mm/mm1/views/businesses/tavern.cpp
engines/mm/mm1/views/businesses/tavern.h
engines/mm/mm1/views/text_view.cpp
engines/mm/utils/strings_data.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c9201a9d399..9eb5a28df8f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1,4 +1,9 @@
dialogs:
+ business:
+ gold: "GOLD= "
+ buy: "'A'-'F' TO BUY\r(- = CANT USE)"
+ sell: "'A'-'F' TO SELL"
+ gather: "'G' GATHER GOLD\r'#' OTHER CHAR"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index ce58b5a02ae..7c35d0abdbf 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -74,7 +74,7 @@ struct Character {
uint8 _sp1 = 0, _sp2 = 0;
uint16 _gems = 0;
uint16 _hp = 0, _hp2 = 0, _hpMax = 0;
- uint16 _gold = 0;
+ uint32 _gold = 0;
byte _ac = 0;
uint8 _food = 0;
uint8 _condition = 0;
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/businesses/business.cpp
index 567a033f188..5952c792dfa 100644
--- a/engines/mm/mm1/views/businesses/business.cpp
+++ b/engines/mm/mm1/views/businesses/business.cpp
@@ -31,6 +31,24 @@ Business::Business(const Common::String &name) : TextView(name) {
_bounds = getLineBounds(17, 24);
}
+void Business::drawInitial() {
+ clearSurface();
+ writeString(0, 0, g_globals->_currCharacter->_name);
+ newLine();
+ writeString(STRING["dialogs.business.gold"]);
+ writeNumber(g_globals->_currCharacter->_gold);
+ newLine();
+ newLine();
+ writeString(_modeString);
+ writeString(0, 6, STRING["dialogs.misc.go_back"]);
+}
+
+void Business::newLine() {
+ _textPos.x = 0;
+ if (++_textPos.y >= 24)
+ _textPos.y = 0;
+}
+
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/business.h b/engines/mm/mm1/views/businesses/business.h
index 2db1376817c..18b3646bab6 100644
--- a/engines/mm/mm1/views/businesses/business.h
+++ b/engines/mm/mm1/views/businesses/business.h
@@ -30,6 +30,19 @@ namespace Views {
namespace Businesses {
class Business : public TextView {
+protected:
+ Common::String _modeString;
+protected:
+ /**
+ * Draws the initial display for the business
+ */
+ void drawInitial();
+
+ /**
+ * Move text position to the next line
+ */
+ void newLine();
+
public:
Business(const Common::String &name);
virtual ~Business() {}
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
index 8af2aad3a81..1a74245602c 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -28,6 +28,7 @@ namespace Views {
namespace Businesses {
Tavern::Tavern() : Business("Tavern") {
+ _modeString = STRING["dialogs.business.gather"];
}
bool Tavern::msgFocus(const FocusMessage &msg) {
@@ -37,11 +38,22 @@ bool Tavern::msgFocus(const FocusMessage &msg) {
}
bool Tavern::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ }
+
return true;
}
void Tavern::draw() {
-
+ switch (_mode) {
+ case INITIAL:
+ drawInitial();
+
+ break;
+ default:
+ break;
+ }
}
} // namespace Businesses
diff --git a/engines/mm/mm1/views/businesses/tavern.h b/engines/mm/mm1/views/businesses/tavern.h
index b3f970eff10..2816450d742 100644
--- a/engines/mm/mm1/views/businesses/tavern.h
+++ b/engines/mm/mm1/views/businesses/tavern.h
@@ -31,6 +31,8 @@ namespace Businesses {
class Tavern : public Business {
private:
+ enum Mode { INITIAL };
+ Mode _mode = INITIAL;
int _val1 = 0;
public:
Tavern();
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 8522178e0e0..2cf9dcbc782 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -37,13 +37,18 @@ TextView::TextView(const Common::String &name, UIElement *owner) :
}
void TextView::writeChar(char c) {
- Graphics::ManagedSurface s = getSurface();
- g_globals->_font.drawChar(&s, c,
- _textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
-
- if (++_textPos.x == TEXT_W) {
+ if (c == '\r' || c == '\n') {
_textPos.x = 0;
- ++_textPos.y;
+ _textPos.y++;
+ } else {
+ Graphics::ManagedSurface s = getSurface();
+ g_globals->_font.drawChar(&s, c,
+ _textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
+
+ if (++_textPos.x == TEXT_W) {
+ _textPos.x = 0;
+ ++_textPos.y;
+ }
}
}
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
index bf40f4fd602..159dd47812d 100644
--- a/engines/mm/utils/strings_data.cpp
+++ b/engines/mm/utils/strings_data.cpp
@@ -69,9 +69,10 @@ bool StringsData::load(const Common::String &filename) {
// Replace any sequences
for (uint i = 0; i < value.size(); ++i) {
- if (value[i] == '\\' && value[i + 1] == '\n') {
+ if (value[i] == '\\' && (value[i + 1] == 'n' ||
+ value[i + 1] == 'r')) {
value.deleteChar(i);
- value.setChar(i, '\n');
+ value.setChar('\n', i);
} else if (value[i] == '"' && value[i + 1] == '"') {
value.deleteChar(i);
}
Commit: afb72630aa7fbc5b6cf54235bef4b56747bf4bd5
https://github.com/scummvm/scummvm/commit/afb72630aa7fbc5b6cf54235bef4b56747bf4bd5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: Remainder of initial tavern display, leaving tavern
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/businesses/business.cpp
engines/mm/mm1/views/businesses/business.h
engines/mm/mm1/views/businesses/tavern.cpp
engines/mm/mm1/views/businesses/tavern.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9eb5a28df8f..9592ec37cca 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -74,6 +74,10 @@ dialogs:
ready:
1: " ARE YOU READY? "
2: "THEN PRESS ENTER!"
+ tavern:
+ drink: "A) HAVE A DRINK\r"
+ tip: "B) TIP BARTENDER\r"
+ listen: "C) LISTEN FOR RUMORS"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index b222427f0dd..895bd7e3fa4 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -30,9 +30,10 @@
namespace MM {
namespace MM1 {
-namespace Maps {
-Maps *g_maps;
+Maps::Maps *g_maps;
+
+namespace Maps {
/** PLACEHOLDER MAPS **/
#define PLACEHOLDER(SUFFIX, INDEX, NAME, ID) \
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index aff82a37064..1e60a91602e 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -154,9 +154,10 @@ public:
void clearSpecial();
};
-extern Maps *g_maps;
-
} // namespace Maps
+
+extern Maps::Maps *g_maps;
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/businesses/business.cpp
index 5952c792dfa..8a9cfe5754d 100644
--- a/engines/mm/mm1/views/businesses/business.cpp
+++ b/engines/mm/mm1/views/businesses/business.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views/businesses/business.h"
+#include "mm/mm1/maps/maps.h"
#include "mm/mm1/globals.h"
namespace MM {
@@ -49,6 +50,16 @@ void Business::newLine() {
_textPos.y = 0;
}
+void Business::leave() {
+ SWAP(g_maps->_forwardMask, g_maps->_backwardsMask);
+ SWAP(g_maps->_leftMask, g_maps->_rightMask);
+ SWAP(g_maps->_forwardOffset, g_maps->_backwardsOffset);
+ SWAP(g_maps->_leftOffset, g_maps->_rightOffset);
+
+ close();
+ g_events->redraw();
+}
+
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/business.h b/engines/mm/mm1/views/businesses/business.h
index 18b3646bab6..b476ce07870 100644
--- a/engines/mm/mm1/views/businesses/business.h
+++ b/engines/mm/mm1/views/businesses/business.h
@@ -43,6 +43,11 @@ protected:
*/
void newLine();
+ /**
+ * Leave the business
+ */
+ void leave();
+
public:
Business(const Common::String &name);
virtual ~Business() {}
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
index 1a74245602c..f11bb733705 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -39,7 +39,7 @@ bool Tavern::msgFocus(const FocusMessage &msg) {
bool Tavern::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
- close();
+ leave();
}
return true;
@@ -49,13 +49,19 @@ void Tavern::draw() {
switch (_mode) {
case INITIAL:
drawInitial();
-
+ drawInitialRight();
break;
default:
break;
}
}
+void Tavern::drawInitialRight() {
+ writeString(20, 1, STRING["dialogs.tavern.drink"]);
+ writeString(20, 2, STRING["dialogs.tavern.tip"]);
+ writeString(20, 3, STRING["dialogs.tavern.listen"]);
+}
+
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/tavern.h b/engines/mm/mm1/views/businesses/tavern.h
index 2816450d742..eaecbae5eae 100644
--- a/engines/mm/mm1/views/businesses/tavern.h
+++ b/engines/mm/mm1/views/businesses/tavern.h
@@ -34,6 +34,12 @@ private:
enum Mode { INITIAL };
Mode _mode = INITIAL;
int _val1 = 0;
+private:
+ /**
+ * Draw the right hand side options in the
+ * initial tavern display
+ */
+ void drawInitialRight();
public:
Tavern();
virtual ~Tavern() {}
Commit: 6df7a8c87ff96dcdc48879cd16c9a0c90bc670ea
https://github.com/scummvm/scummvm/commit/6df7a8c87ff96dcdc48879cd16c9a0c90bc670ea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: More implementation of Tavern
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/globals.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/views/businesses/tavern.cpp
engines/mm/mm1/views/businesses/tavern.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9592ec37cca..791b288f795 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -78,6 +78,30 @@ dialogs:
drink: "A) HAVE A DRINK\r"
tip: "B) TIP BARTENDER\r"
listen: "C) LISTEN FOR RUMORS"
+ no_rumors: "NO RUMORS TODAY."
+ great_stuff: "GREAT STUFF!"
+ you_feel_sick: "YOU FEEL SICK!!"
+ have_a_drink: "HAVE A DRINK, THEN WE'LL TALK."
+ thanks: "THANKS A LOT, HAVE ANOTHER ROUND!"
+ terrible: "YOU LOOK TERRIBLE, GO SEE THE CLERICS."
+ rumors:
+ none: "NO RUMORS TODAY."
+ 0: "ALL PORTALS ARE CONNECTED"
+ 1: "SORPIGAL HAS 8 STATUES"
+ 2: "THE BROTHERS LIVE BY DOCKS"
+ 3: "SOME CAVES HAVE MORE THAN ONE EXIT"
+ 4: "THE ICE PRINCESS HAS THE KEY"
+ 5: "THE DESERT HAS MANY OASES"
+ 6: "THE SWAMP WAS ONCE A CITY OF GOLD"
+ 7: "PORTSMITH AND MEN DON'T MIX"
+ 8: "MOST TOWNS HAVE CAVERNS BELOW"
+ 9: "VARN IS NOT WHAT IT APPEARS TO BE"
+ 10: "KILBURN IS NEAR THE WYVERN PEAKS"
+ 11: "A DRAGONS BREATH IS ONLY AS STRONG AS IT'S CONDITION"
+ 12: "THE KING IS IN SECLUSION"
+ 14: "THE INNER SANCTUM IS A MYTH"
+ 15: "THE CANINE HAS THE KEY"
+ 16: "SCUMMVM IS TOTALLY AWESOME!"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 7c35d0abdbf..a0e89631cf3 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -85,6 +85,9 @@ struct Character {
int _v58, _v59, _v62, _v63, _v64, _v65;
int _v66, _v67, _v6c, _v6f;
+ // Non persistent fields
+ byte _numDrinks = 0;
+
void synchronize(Common::Serializer &s);
void clear();
};
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 44991b1b2da..b80c72e0251 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -30,9 +30,6 @@
namespace MM {
namespace MM1 {
-#define FRAME_RATE 20
-#define FRAME_DELAY (1000 / FRAME_RATE)
-
Events *g_events;
Events::Events(bool enhancedMode) : UIElement("", nullptr),
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 2068f669660..747f5ab708d 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -30,6 +30,9 @@
namespace MM {
namespace MM1 {
+#define FRAME_RATE 20
+#define FRAME_DELAY (1000 / FRAME_RATE)
+
class Events;
class UIElement {
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index efc0feca6c8..882aa37363f 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -43,6 +43,7 @@ public:
Maps::Maps _maps;
bool _intangible = false; // Console flag
BitmapFont _font;
+ bool _heardRumor = false;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index dfbebaeb9ac..4f8c3e8c46a 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -38,6 +38,8 @@ Map::Map(uint index, const Common::String &name, uint16 id) :
void Map::load() {
loadMazeData();
loadOverlay();
+
+ g_globals->_heardRumor = false;
}
void Map::loadMazeData() {
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
index f11bb733705..d884a6827d6 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -20,13 +20,18 @@
*/
#include "mm/mm1/views/businesses/tavern.h"
+#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Businesses {
+#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
+
Tavern::Tavern() : Business("Tavern") {
_modeString = STRING["dialogs.business.gather"];
}
@@ -38,22 +43,59 @@ bool Tavern::msgFocus(const FocusMessage &msg) {
}
bool Tavern::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
leave();
+ break;
+ case Common::KEYCODE_a:
+ haveADrink();
+ break;
+ case Common::KEYCODE_b:
+ tipBartender();
+ break;
+ case Common::KEYCODE_c:
+ listenForRumors();
+ break;
+ case Common::KEYCODE_g:
+ gatherGold();
+ redraw();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6: {
+ uint charIndex = msg.keycode - Common::KEYCODE_1;
+ if (charIndex < g_globals->_party.size()) {
+ g_globals->_currCharacter = &g_globals->_party[charIndex];
+ redraw();
+ }
+ break;
+ }
+ default:
+ break;
}
return true;
}
void Tavern::draw() {
+ drawInitial();
+ drawInitialRight();
+
switch (_mode) {
- case INITIAL:
- drawInitial();
- drawInitialRight();
+ case DRINK:
+ drawDrink();
+ break;
+ case RUMOR:
+ drawRumor();
break;
default:
break;
}
+
+ _mode = INITIAL;
}
void Tavern::drawInitialRight() {
@@ -62,6 +104,60 @@ void Tavern::drawInitialRight() {
writeString(20, 3, STRING["dialogs.tavern.listen"]);
}
+void Tavern::drawDrink() {
+ clearLines(3, 7);
+ writeString(0, 5, STRING["dialogs.tavern.terrible"]);
+}
+
+void Tavern::drawRumor() {
+ Common::String msg = STRING["dialogs.tavern.rumors.none"];
+ if (!g_globals->_heardRumor) {
+ g_globals->_heardRumor = true;
+ msg = STRING[Common::String::format(
+ "dialogs.tavern.rumors.%d",
+ g_engine->getRandomNumber(16))];
+ }
+
+ clearLines(3, 7);
+ writeString(0, 5, msg);
+}
+
+void Tavern::haveADrink() {
+ _mode = DRINK;
+ Sound::sound(SOUND_2);
+ _timeoutCtr = DISPLAY_TIMEOUT;
+ redraw();
+}
+
+void Tavern::tipBartender() {
+
+}
+
+void Tavern::listenForRumors() {
+ _mode = RUMOR;
+ _timeoutCtr = DISPLAY_TIMEOUT;
+ redraw();
+}
+
+void Tavern::gatherGold() {
+ uint total = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ total += g_globals->_party[i]._gold;
+ g_globals->_party[i]._gold = 0;
+ }
+
+ g_globals->_currCharacter->_gold = total;
+}
+
+bool Tavern::tick() {
+ if (_timeoutCtr && --_timeoutCtr == 0) {
+ _mode = INITIAL;
+ redraw();
+ }
+
+ return Business::tick();
+}
+
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/tavern.h b/engines/mm/mm1/views/businesses/tavern.h
index eaecbae5eae..108380f89ac 100644
--- a/engines/mm/mm1/views/businesses/tavern.h
+++ b/engines/mm/mm1/views/businesses/tavern.h
@@ -31,15 +31,47 @@ namespace Businesses {
class Tavern : public Business {
private:
- enum Mode { INITIAL };
+ enum Mode { INITIAL, DRINK, RUMOR };
Mode _mode = INITIAL;
int _val1 = 0;
+ int _timeoutCtr = 0;
private:
/**
* Draw the right hand side options in the
* initial tavern display
*/
void drawInitialRight();
+
+ /**
+ * Draws the drink response
+ */
+ void drawDrink();
+
+ /**
+ * Display a rumor
+ */
+ void drawRumor();
+
+ /**
+ * Have a drink
+ */
+ void haveADrink();
+
+ /**
+ * Tip the bartender
+ */
+ void tipBartender();
+
+ /**
+ * Listen for rumors
+ */
+ void listenForRumors();
+
+ /**
+ * Gathers all the party gold to the current character
+ */
+ void gatherGold();
+
public:
Tavern();
virtual ~Tavern() {}
@@ -47,6 +79,7 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
void draw() override;
+ bool tick() override;
};
} // namespace Businesses
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 2cf9dcbc782..7f9d1ae59ad 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -90,6 +90,11 @@ void TextView::clearSurface() {
_textPos.x = _textPos.y = 0;
}
+void TextView::clearLines(int y1, int y2) {
+ Graphics::ManagedSurface s = getSurface();
+ s.fillRect(getLineBounds(y1, y2), 0);
+}
+
void TextView::drawTextBorder() {
Graphics::ManagedSurface surf = getSurface();
clearSurface();
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 98310e69b3e..9ec1f92f106 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -64,6 +64,11 @@ protected:
*/
void clearSurface();
+ /**
+ * Clear area covered by the given text lines
+ */
+ void clearLines(int y1, int y2);
+
/**
* Draws a text border
*/
Commit: 7b9816c75132d501ec5ee26fecc32ff59580bc4c
https://github.com/scummvm/scummvm/commit/7b9816c75132d501ec5ee26fecc32ff59580bc4c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: Simply tavern message display
Changed paths:
engines/mm/mm1/views/businesses/business.cpp
engines/mm/mm1/views/businesses/business.h
engines/mm/mm1/views/businesses/tavern.cpp
engines/mm/mm1/views/businesses/tavern.h
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/businesses/business.cpp
index 8a9cfe5754d..4a416c64343 100644
--- a/engines/mm/mm1/views/businesses/business.cpp
+++ b/engines/mm/mm1/views/businesses/business.cpp
@@ -28,11 +28,13 @@ namespace MM1 {
namespace Views {
namespace Businesses {
+#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
+
Business::Business(const Common::String &name) : TextView(name) {
_bounds = getLineBounds(17, 24);
}
-void Business::drawInitial() {
+void Business::draw() {
clearSurface();
writeString(0, 0, g_globals->_currCharacter->_name);
newLine();
@@ -44,6 +46,12 @@ void Business::drawInitial() {
writeString(0, 6, STRING["dialogs.misc.go_back"]);
}
+void Business::displayMessage(const Common::String &msg) {
+ clearLines(3, 7);
+ writeString(0, 5, msg);
+ _timeoutCtr = DISPLAY_TIMEOUT;
+}
+
void Business::newLine() {
_textPos.x = 0;
if (++_textPos.y >= 24)
@@ -60,6 +68,14 @@ void Business::leave() {
g_events->redraw();
}
+bool Business::tick() {
+ if (_timeoutCtr && --_timeoutCtr == 0) {
+ redraw();
+ }
+
+ return TextView::tick();
+}
+
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/business.h b/engines/mm/mm1/views/businesses/business.h
index b476ce07870..1db4f1d4e72 100644
--- a/engines/mm/mm1/views/businesses/business.h
+++ b/engines/mm/mm1/views/businesses/business.h
@@ -30,13 +30,16 @@ namespace Views {
namespace Businesses {
class Business : public TextView {
+private:
+ int _timeoutCtr;
protected:
Common::String _modeString;
protected:
/**
- * Draws the initial display for the business
+ * Clears the bottom part of the window and
+ * displays a message
*/
- void drawInitial();
+ void displayMessage(const Common::String &msg);
/**
* Move text position to the next line
@@ -48,9 +51,19 @@ protected:
*/
void leave();
+ /**
+ * Subtract gold
+ */
public:
Business(const Common::String &name);
virtual ~Business() {}
+
+ /**
+ * Draws the initial display for the business
+ */
+ void draw() override;
+
+ bool tick() override;
};
} // namespace Businesses
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
index d884a6827d6..615980db479 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -30,8 +30,6 @@ namespace MM1 {
namespace Views {
namespace Businesses {
-#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
-
Tavern::Tavern() : Business("Tavern") {
_modeString = STRING["dialogs.business.gather"];
}
@@ -81,35 +79,23 @@ bool Tavern::msgKeypress(const KeypressMessage &msg) {
}
void Tavern::draw() {
- drawInitial();
- drawInitialRight();
-
- switch (_mode) {
- case DRINK:
- drawDrink();
- break;
- case RUMOR:
- drawRumor();
- break;
- default:
- break;
- }
-
- _mode = INITIAL;
-}
+ Business::draw();
-void Tavern::drawInitialRight() {
writeString(20, 1, STRING["dialogs.tavern.drink"]);
writeString(20, 2, STRING["dialogs.tavern.tip"]);
writeString(20, 3, STRING["dialogs.tavern.listen"]);
}
-void Tavern::drawDrink() {
- clearLines(3, 7);
- writeString(0, 5, STRING["dialogs.tavern.terrible"]);
+void Tavern::haveADrink() {
+ Sound::sound(SOUND_2);
+ displayMessage(STRING["dialogs.tavern.terrible"]);
+}
+
+void Tavern::tipBartender() {
+
}
-void Tavern::drawRumor() {
+void Tavern::listenForRumors() {
Common::String msg = STRING["dialogs.tavern.rumors.none"];
if (!g_globals->_heardRumor) {
g_globals->_heardRumor = true;
@@ -118,25 +104,7 @@ void Tavern::drawRumor() {
g_engine->getRandomNumber(16))];
}
- clearLines(3, 7);
- writeString(0, 5, msg);
-}
-
-void Tavern::haveADrink() {
- _mode = DRINK;
- Sound::sound(SOUND_2);
- _timeoutCtr = DISPLAY_TIMEOUT;
- redraw();
-}
-
-void Tavern::tipBartender() {
-
-}
-
-void Tavern::listenForRumors() {
- _mode = RUMOR;
- _timeoutCtr = DISPLAY_TIMEOUT;
- redraw();
+ displayMessage(msg);
}
void Tavern::gatherGold() {
@@ -149,15 +117,6 @@ void Tavern::gatherGold() {
g_globals->_currCharacter->_gold = total;
}
-bool Tavern::tick() {
- if (_timeoutCtr && --_timeoutCtr == 0) {
- _mode = INITIAL;
- redraw();
- }
-
- return Business::tick();
-}
-
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/tavern.h b/engines/mm/mm1/views/businesses/tavern.h
index 108380f89ac..73c54f92774 100644
--- a/engines/mm/mm1/views/businesses/tavern.h
+++ b/engines/mm/mm1/views/businesses/tavern.h
@@ -31,27 +31,8 @@ namespace Businesses {
class Tavern : public Business {
private:
- enum Mode { INITIAL, DRINK, RUMOR };
- Mode _mode = INITIAL;
int _val1 = 0;
- int _timeoutCtr = 0;
private:
- /**
- * Draw the right hand side options in the
- * initial tavern display
- */
- void drawInitialRight();
-
- /**
- * Draws the drink response
- */
- void drawDrink();
-
- /**
- * Display a rumor
- */
- void drawRumor();
-
/**
* Have a drink
*/
@@ -79,7 +60,6 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
void draw() override;
- bool tick() override;
};
} // namespace Businesses
Commit: d38c12fde799a729dd2cc3b94f0d863ac52d8b31
https://github.com/scummvm/scummvm/commit/d38c12fde799a729dd2cc3b94f0d863ac52d8b31
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: Further implementing tavern
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/businesses/business.cpp
engines/mm/mm1/views/businesses/business.h
engines/mm/mm1/views/businesses/tavern.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 791b288f795..0dcbecb0bf1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -82,8 +82,8 @@ dialogs:
great_stuff: "GREAT STUFF!"
you_feel_sick: "YOU FEEL SICK!!"
have_a_drink: "HAVE A DRINK, THEN WE'LL TALK."
- thanks: "THANKS A LOT, HAVE ANOTHER ROUND!"
- terrible: "YOU LOOK TERRIBLE, GO SEE THE CLERICS."
+ have_another_round: "THANKS A LOT, HAVE ANOTHER ROUND!"
+ go_see_clerics: "YOU LOOK TERRIBLE, GO SEE THE CLERICS."
rumors:
none: "NO RUMORS TODAY."
0: "ALL PORTALS ARE CONNECTED"
@@ -97,11 +97,41 @@ dialogs:
8: "MOST TOWNS HAVE CAVERNS BELOW"
9: "VARN IS NOT WHAT IT APPEARS TO BE"
10: "KILBURN IS NEAR THE WYVERN PEAKS"
- 11: "A DRAGONS BREATH IS ONLY AS STRONG AS IT'S CONDITION"
+ 11: "A DRAGONS BREATH IS ONLY AS STRONG\x8BAS IT'S CONDITION"
12: "THE KING IS IN SECLUSION"
14: "THE INNER SANCTUM IS A MYTH"
15: "THE CANINE HAS THE KEY"
16: "SCUMMVM IS TOTALLY AWESOME!"
+ tips:
+ 1_1: "SEE MAN IN CAVE BELOW (1,2)"
+ 1_2: "CHECK WALLS NEAR (12,3)"
+ 1_3: "STATUE AT (2,4) IS YOUR FIRST JOB"
+ 1_4: "SIMILAR PIECES OF A PUZZLE MAY NOT\8DBELONG TO THE SAME PUZZLE"
+ 2_1: "SEEK QUESTS BEHIND MOONS"
+ 2_2: "THE QUEEN CAN BE HELPFUL"
+ 2_3: "THE BEASTS ARE ON THE MAP"
+ 2_4: "ISLANDS LIKE COLORS ARE UNKNOWN\x8DUNTIL DISCOVERED"
+ 3_1: "ATTACKS SHOULD BE CONCENTRATED"
+ 3_2: "DUE NORTH IS THE CAVE OF SQUARE MAGIC"
+ 3_3: "SECRET DOORS ARE ABUNDANT"
+ 3_4: "THE DEMON AND THE MAZE ARE ONE"
+ 4_1: "TELGORAN IS IN S.E. MAZE"
+ 4_2: "SOME ITEMS GIVE PROTECTION"
+ 4_3: "DRAGADUNE HOLDS MANY GEMS"
+ 4_4: "DONATIONS HELP ON JUDGEMENT DAY"
+ 5_1: "AGAR LIVES BEHIND THE INN"
+ 5_2: "FIND THE PRISONER"
+ 5_3: "BARRIERS GUARD WEALTH"
+ 5_4: "THE MAGIC TOTAL IS 34"
+ unsure:
+ 6: "SERVICES RENDERED, SECRETS UNFOLD\nTHE BROTHERS TOGETHER\nLEAD TO TREASURES UNTOLD\n\nFIVE TOWNS YOU MUST TRAVEL\nFOR THIS QUEST TO UNRAVEL"
+ 7: "SEEK THE WIZARD RANALOU\nIN HIS LAIR AT THE KORIN BLUFFS\nSIX CASTLES HE WILL SEND YOU TO\nBUT DOOM WILL BE QUITE TOUGH!\nCRUELTY AND KINDNESS\nMEASURED THROUGHOUT\nJUDGEMENT DAY IS THEN SOUGHT OUT"
+ 8: "ONE BY WATER, ONE BY LAND\nONE BY AIR, AND ONE BY SAND\nTHE WHEEL OF LUCK\nWILL FAVORABLY PAY, THE MORE OF THESE\nMENACING BEASTS YOU SLAY!\nALTHOUGH WISHES MAY COME TRUE\nALL THE BEASTS WILL BECOME ANEW"
+ 9: "THERE ARE MANY DUNGEONS LIKE ME\nFIND THE RIGHT PAIR\nAND YOU'LL DISCOVER THE KEY\nTHE ANCIENT SEER OG HAS LOST HIS SIGHT\nTHE IDOLS WILL HELP TO END HIS PLIGHT"
+ 10: "IN HONOR OF CORAK...\n\nFOR HIS MAPPING EXPEDITION\nOF THE LAND OF VARN AND REDISCOVERY\nOF THE LOST TOWN OF DUSK"
+ 11: "IN HONOR OF GALA...\n\nFOR HER BRAVE ATTEMPT TO WORK WITH THE\nSAVAGES OF THE VOLCANIC ISLES"
+ 12: "IN MEMORY OF A TIME LONG AGO...\n\nBEFORE THE DAYS WHEN THE TOWNS\nMOVED UNDERGROUND, DRAGONS WERE\nFEW AND FAR BETWEEN"
+ 13: "THIS BEAST ONCE ROAMED THE\nENCHANTED FOREST AND NOW RULES\nA GREAT FORTRESS THERE"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
@@ -136,6 +166,7 @@ dialogs:
go_back: "'ESC' TO GO BACK"
no_characters: "NO AVAILABLE CHARACTERS"
some_characters: "AVAILABLE CHARACTERS"
+ not_enough_gold: "*** NOT ENOUGH GOLD ***"
stats:
none: "NONE"
inventory: "-----<EQUIPPED>----------<BACKPACK>----".
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/businesses/business.cpp
index 4a416c64343..04128a2eda8 100644
--- a/engines/mm/mm1/views/businesses/business.cpp
+++ b/engines/mm/mm1/views/businesses/business.cpp
@@ -22,13 +22,14 @@
#include "mm/mm1/views/businesses/business.h"
#include "mm/mm1/maps/maps.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Businesses {
-#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
+#define DISPLAY_TIMEOUT (5 * FRAME_RATE)
Business::Business(const Common::String &name) : TextView(name) {
_bounds = getLineBounds(17, 24);
@@ -46,9 +47,9 @@ void Business::draw() {
writeString(0, 6, STRING["dialogs.misc.go_back"]);
}
-void Business::displayMessage(const Common::String &msg) {
+void Business::displayMessage(int x, const Common::String &msg) {
clearLines(3, 7);
- writeString(0, 5, msg);
+ writeString(x, 5, msg);
_timeoutCtr = DISPLAY_TIMEOUT;
}
@@ -58,6 +59,21 @@ void Business::newLine() {
_textPos.y = 0;
}
+bool Business::subtractGold(uint amount) {
+ if (g_globals->_currCharacter->_gold < amount) {
+ notEnoughGold();
+ return false;
+ } else {
+ g_globals->_currCharacter->_gold -= amount;
+ return true;
+ }
+}
+
+void Business::notEnoughGold() {
+ Sound::sound(SOUND_2);
+ displayMessage(STRING["dialogs.misc.not_enough_gold"]);
+}
+
void Business::leave() {
SWAP(g_maps->_forwardMask, g_maps->_backwardsMask);
SWAP(g_maps->_leftMask, g_maps->_rightMask);
diff --git a/engines/mm/mm1/views/businesses/business.h b/engines/mm/mm1/views/businesses/business.h
index 1db4f1d4e72..a67d5bd2aa9 100644
--- a/engines/mm/mm1/views/businesses/business.h
+++ b/engines/mm/mm1/views/businesses/business.h
@@ -39,7 +39,10 @@ protected:
* Clears the bottom part of the window and
* displays a message
*/
- void displayMessage(const Common::String &msg);
+ void displayMessage(int x, const Common::String &msg);
+ void displayMessage(const Common::String &msg) {
+ displayMessage(0, msg);
+ }
/**
* Move text position to the next line
@@ -52,8 +55,14 @@ protected:
void leave();
/**
- * Subtract gold
+ * Subtract gold from current character
*/
+ bool subtractGold(uint amount);
+
+ /**
+ * Displays not enough gold
+ */
+ void notEnoughGold();
public:
Business(const Common::String &name);
virtual ~Business() {}
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
index 615980db479..1d0fe5d4df1 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -87,12 +87,40 @@ void Tavern::draw() {
}
void Tavern::haveADrink() {
- Sound::sound(SOUND_2);
- displayMessage(STRING["dialogs.tavern.terrible"]);
+ if (g_globals->_currCharacter->_condition) {
+ Sound::sound(SOUND_2);
+ displayMessage(STRING["dialogs.tavern.terrible"]);
+ } else if (subtractGold(1)) {
+ if (++g_globals->_currCharacter->_numDrinks < 3 ||
+ g_engine->getRandomNumber(10) <
+ g_globals->_currCharacter->_end) {
+ displayMessage(STRING["dialogs.tavern.great_stuff"]);
+ } else {
+ if (!(g_globals->_currCharacter->_condition & BAD_CONDITION))
+ g_globals->_currCharacter->_condition |= POISONED;
+
+ Sound::sound(SOUND_2);
+ displayMessage(13, STRING["dialogs.tavern.you_feel_sick"]);
+ }
+ }
}
void Tavern::tipBartender() {
-
+ if (g_globals->_currCharacter->_condition) {
+ displayMessage(STRING["dialogs.tavern.go_see_clerics"]);
+ } else if (subtractGold(1)) {
+ if (g_globals->_currCharacter->_numDrinks == 0) {
+ displayMessage(STRING["dialogs.tavern.have_a_drink"]);
+ } else if (g_engine->getRandomNumber(3) != 3) {
+ displayMessage(STRING["dialogs.tavern.have_another_drink"]);
+ } else {
+ int townNum = g_maps->_currentMap->dataByte(0);
+ displayMessage(STRING[Common::String::format(
+ "dialogs.tavern.tips.%d_%d",
+ townNum, g_globals->_currCharacter->_numDrinks
+ )]);
+ }
+ }
}
void Tavern::listenForRumors() {
Commit: d0bc2a4796ee8f6829006908e28e93956aa7778d
https://github.com/scummvm/scummvm/commit/d0bc2a4796ee8f6829006908e28e93956aa7778d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: Workaround for 8Bh charcaters in strings
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/text_view.cpp
engines/mm/utils/strings_data.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 0dcbecb0bf1..ad0ebdc4f1b 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -123,15 +123,15 @@ dialogs:
5_2: "FIND THE PRISONER"
5_3: "BARRIERS GUARD WEALTH"
5_4: "THE MAGIC TOTAL IS 34"
- unsure:
- 6: "SERVICES RENDERED, SECRETS UNFOLD\nTHE BROTHERS TOGETHER\nLEAD TO TREASURES UNTOLD\n\nFIVE TOWNS YOU MUST TRAVEL\nFOR THIS QUEST TO UNRAVEL"
- 7: "SEEK THE WIZARD RANALOU\nIN HIS LAIR AT THE KORIN BLUFFS\nSIX CASTLES HE WILL SEND YOU TO\nBUT DOOM WILL BE QUITE TOUGH!\nCRUELTY AND KINDNESS\nMEASURED THROUGHOUT\nJUDGEMENT DAY IS THEN SOUGHT OUT"
- 8: "ONE BY WATER, ONE BY LAND\nONE BY AIR, AND ONE BY SAND\nTHE WHEEL OF LUCK\nWILL FAVORABLY PAY, THE MORE OF THESE\nMENACING BEASTS YOU SLAY!\nALTHOUGH WISHES MAY COME TRUE\nALL THE BEASTS WILL BECOME ANEW"
- 9: "THERE ARE MANY DUNGEONS LIKE ME\nFIND THE RIGHT PAIR\nAND YOU'LL DISCOVER THE KEY\nTHE ANCIENT SEER OG HAS LOST HIS SIGHT\nTHE IDOLS WILL HELP TO END HIS PLIGHT"
- 10: "IN HONOR OF CORAK...\n\nFOR HIS MAPPING EXPEDITION\nOF THE LAND OF VARN AND REDISCOVERY\nOF THE LOST TOWN OF DUSK"
- 11: "IN HONOR OF GALA...\n\nFOR HER BRAVE ATTEMPT TO WORK WITH THE\nSAVAGES OF THE VOLCANIC ISLES"
- 12: "IN MEMORY OF A TIME LONG AGO...\n\nBEFORE THE DAYS WHEN THE TOWNS\nMOVED UNDERGROUND, DRAGONS WERE\nFEW AND FAR BETWEEN"
- 13: "THIS BEAST ONCE ROAMED THE\nENCHANTED FOREST AND NOW RULES\nA GREAT FORTRESS THERE"
+ unknown:
+ 1: "SERVICES RENDERED, SECRETS UNFOLD\nTHE BROTHERS TOGETHER\nLEAD TO TREASURES UNTOLD\n\nFIVE TOWNS YOU MUST TRAVEL\nFOR THIS QUEST TO UNRAVEL"
+ 2: "SEEK THE WIZARD RANALOU\nIN HIS LAIR AT THE KORIN BLUFFS\nSIX CASTLES HE WILL SEND YOU TO\nBUT DOOM WILL BE QUITE TOUGH!\nCRUELTY AND KINDNESS\nMEASURED THROUGHOUT\nJUDGEMENT DAY IS THEN SOUGHT OUT"
+ 3: "ONE BY WATER, ONE BY LAND\nONE BY AIR, AND ONE BY SAND\nTHE WHEEL OF LUCK\nWILL FAVORABLY PAY, THE MORE OF THESE\nMENACING BEASTS YOU SLAY!\nALTHOUGH WISHES MAY COME TRUE\nALL THE BEASTS WILL BECOME ANEW"
+ 4: "THERE ARE MANY DUNGEONS LIKE ME\nFIND THE RIGHT PAIR\nAND YOU'LL DISCOVER THE KEY\nTHE ANCIENT SEER OG HAS LOST HIS SIGHT\nTHE IDOLS WILL HELP TO END HIS PLIGHT"
+ 5: "IN HONOR OF CORAK...\n\nFOR HIS MAPPING EXPEDITION\nOF THE LAND OF VARN AND REDISCOVERY\nOF THE LOST TOWN OF DUSK"
+ 6: "IN HONOR OF GALA...\n\nFOR HER BRAVE ATTEMPT TO WORK WITH THE\nSAVAGES OF THE VOLCANIC ISLES"
+ 7: "IN MEMORY OF A TIME LONG AGO...\n\nBEFORE THE DAYS WHEN THE TOWNS\nMOVED UNDERGROUND, DRAGONS WERE\nFEW AND FAR BETWEEN"
+ 8: "THIS BEAST ONCE ROAMED THE\nENCHANTED FOREST AND NOW RULES\nA GREAT FORTRESS THERE"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 7f9d1ae59ad..3dfa02ed486 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -59,8 +59,13 @@ void TextView::writeChar(int x, int y, char c) {
}
void TextView::writeString(const Common::String &str) {
- for (const char *s = str.c_str(); *s; ++s)
- writeChar(*s);
+ for (const unsigned char *s = (const unsigned char *)str.c_str(); *s; ++s) {
+ if (*s & 0x80)
+ warning("TODO: Unknown high-bit set in string character");
+
+ char c = (char)(*s & 0x7f);
+ writeChar(c);
+ }
}
void TextView::writeString(int x, int y, const Common::String &str) {
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
index 159dd47812d..4fc4b25cf0d 100644
--- a/engines/mm/utils/strings_data.cpp
+++ b/engines/mm/utils/strings_data.cpp
@@ -70,9 +70,14 @@ bool StringsData::load(const Common::String &filename) {
// Replace any sequences
for (uint i = 0; i < value.size(); ++i) {
if (value[i] == '\\' && (value[i + 1] == 'n' ||
- value[i + 1] == 'r')) {
+ value[i + 1] == 'r')) {
value.deleteChar(i);
value.setChar('\n', i);
+ } else if (!strncmp(value.c_str() + i, "\\x8B", 4)) {
+ value.deleteChar(i);
+ value.deleteChar(i);
+ value.deleteChar(i);
+ value.setChar('\x8B', i);
} else if (value[i] == '"' && value[i + 1] == '"') {
value.deleteChar(i);
}
Commit: 59c398272702900f8eb57fad657220353a979a21
https://github.com/scummvm/scummvm/commit/59c398272702900f8eb57fad657220353a979a21
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:52+01:00
Commit Message:
MM: MM1: Beginning of temple view
Changed paths:
A engines/mm/mm1/views/businesses/temple.cpp
A engines/mm/mm1/views/businesses/temple.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/views/businesses/tavern.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game_view.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ad0ebdc4f1b..619b775a884 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1,5 +1,11 @@
dialogs:
business:
+ titles:
+ 0: "--TRAINING--"
+ 1: "--MARKET--"
+ 2: "--TEMPLE--"
+ 3: "--BLACKSMITH--"
+ 4: "--TAVERN--"
gold: "GOLD= "
buy: "'A'-'F' TO BUY\r(- = CANT USE)"
sell: "'A'-'F' TO SELL"
@@ -74,6 +80,15 @@ dialogs:
ready:
1: " ARE YOU READY? "
2: "THEN PRESS ENTER!"
+ statues:
+ 1: "SERVICES RENDERED, SECRETS UNFOLD\nTHE BROTHERS TOGETHER\nLEAD TO TREASURES UNTOLD\n\nFIVE TOWNS YOU MUST TRAVEL\nFOR THIS QUEST TO UNRAVEL"
+ 2: "SEEK THE WIZARD RANALOU\nIN HIS LAIR AT THE KORIN BLUFFS\nSIX CASTLES HE WILL SEND YOU TO\nBUT DOOM WILL BE QUITE TOUGH!\nCRUELTY AND KINDNESS\nMEASURED THROUGHOUT\nJUDGEMENT DAY IS THEN SOUGHT OUT"
+ 3: "ONE BY WATER, ONE BY LAND\nONE BY AIR, AND ONE BY SAND\nTHE WHEEL OF LUCK\nWILL FAVORABLY PAY, THE MORE OF THESE\nMENACING BEASTS YOU SLAY!\nALTHOUGH WISHES MAY COME TRUE\nALL THE BEASTS WILL BECOME ANEW"
+ 4: "THERE ARE MANY DUNGEONS LIKE ME\nFIND THE RIGHT PAIR\nAND YOU'LL DISCOVER THE KEY\nTHE ANCIENT SEER OG HAS LOST HIS SIGHT\nTHE IDOLS WILL HELP TO END HIS PLIGHT"
+ 5: "IN HONOR OF CORAK...\n\nFOR HIS MAPPING EXPEDITION\nOF THE LAND OF VARN AND REDISCOVERY\nOF THE LOST TOWN OF DUSK"
+ 6: "IN HONOR OF GALA...\n\nFOR HER BRAVE ATTEMPT TO WORK WITH THE\nSAVAGES OF THE VOLCANIC ISLES"
+ 7: "IN MEMORY OF A TIME LONG AGO...\n\nBEFORE THE DAYS WHEN THE TOWNS\nMOVED UNDERGROUND, DRAGONS WERE\nFEW AND FAR BETWEEN"
+ 8: "THIS BEAST ONCE ROAMED THE\nENCHANTED FOREST AND NOW RULES\nA GREAT FORTRESS THERE"
tavern:
drink: "A) HAVE A DRINK\r"
tip: "B) TIP BARTENDER\r"
@@ -123,15 +138,12 @@ dialogs:
5_2: "FIND THE PRISONER"
5_3: "BARRIERS GUARD WEALTH"
5_4: "THE MAGIC TOTAL IS 34"
- unknown:
- 1: "SERVICES RENDERED, SECRETS UNFOLD\nTHE BROTHERS TOGETHER\nLEAD TO TREASURES UNTOLD\n\nFIVE TOWNS YOU MUST TRAVEL\nFOR THIS QUEST TO UNRAVEL"
- 2: "SEEK THE WIZARD RANALOU\nIN HIS LAIR AT THE KORIN BLUFFS\nSIX CASTLES HE WILL SEND YOU TO\nBUT DOOM WILL BE QUITE TOUGH!\nCRUELTY AND KINDNESS\nMEASURED THROUGHOUT\nJUDGEMENT DAY IS THEN SOUGHT OUT"
- 3: "ONE BY WATER, ONE BY LAND\nONE BY AIR, AND ONE BY SAND\nTHE WHEEL OF LUCK\nWILL FAVORABLY PAY, THE MORE OF THESE\nMENACING BEASTS YOU SLAY!\nALTHOUGH WISHES MAY COME TRUE\nALL THE BEASTS WILL BECOME ANEW"
- 4: "THERE ARE MANY DUNGEONS LIKE ME\nFIND THE RIGHT PAIR\nAND YOU'LL DISCOVER THE KEY\nTHE ANCIENT SEER OG HAS LOST HIS SIGHT\nTHE IDOLS WILL HELP TO END HIS PLIGHT"
- 5: "IN HONOR OF CORAK...\n\nFOR HIS MAPPING EXPEDITION\nOF THE LAND OF VARN AND REDISCOVERY\nOF THE LOST TOWN OF DUSK"
- 6: "IN HONOR OF GALA...\n\nFOR HER BRAVE ATTEMPT TO WORK WITH THE\nSAVAGES OF THE VOLCANIC ISLES"
- 7: "IN MEMORY OF A TIME LONG AGO...\n\nBEFORE THE DAYS WHEN THE TOWNS\nMOVED UNDERGROUND, DRAGONS WERE\nFEW AND FAR BETWEEN"
- 8: "THIS BEAST ONCE ROAMED THE\nENCHANTED FOREST AND NOW RULES\nA GREAT FORTRESS THERE"
+ temple:
+ service_cost: "SERVICE COST"
+ a: "A) RESTORE HEALTH"
+ b: "B) UNCURSE ITEMS"
+ c: "C) RESTORE ALIGN"
+ d: "D) MAKE DONATION"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
@@ -484,32 +496,27 @@ stats:
254: "EYE OF GORDOS"
255: "(USELESS ITEM)"
maps:
- businesses:
- 0: "--TRAINING--"
- 1: "--MARKET--"
- 2: "--TEMPLE--"
- 3: "--BLACKSMITH--"
- 4: "--TAVERN--"
map00:
sign: "A SIGN ABOVE THE DOOR READS: "
+ tavern: "YE OLDE HOGGE TAVERN"
+ temple: "TEMPLE MOONSHADOW"
+ training: "OTTO'S TRAINING"
+ jail: "JAIL. KEEP OUT!"
eulards: """EULARDS FINE FOODS"""
blacksmith: """B AND B BLACKSMITHING"""
inn: """THE INN OF SORPIGAL"""
- tavern: "STEP UP TO THE BAR (Y/N)?"
+
+ tavern_inside: "STEP UP TO THE BAR (Y/N)?"
+ temple_inside: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
c9d3: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
ca69: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
food: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
- cb70: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
cbc8: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
cd2e: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
cd53: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
- cd7c: "YE OLDE HOGGE TAVERN"
- cd93: "TEMPLE MOONSHADOW"
- cda7: "OTTO'S TRAINING"
- cdb9: "JAIL. KEEP OUT!"
cdf3: "TRAP DOOR!"
cdfe: ", LEVITATION SAVES YOU!"
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 12a06bf7ff5..286731a2ba4 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -105,14 +105,23 @@ void Map00::special04() {
void Map00::special05() {
Sound::sound(SOUND_2);
g_events->msgInfo(InfoMessage(
- STRING["maps.map00.tavern"],
+ STRING["maps.map00.tavern_inside"],
[]() {
g_events->addView("TAVERN");
}
));
}
-void Map00::special06() { warning("special06"); }
+void Map00::special06() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ STRING["maps.map00.temple_inside"],
+ []() {
+ g_events->addView("TEMPLE");
+ }
+ ));
+}
+
void Map00::special07() { warning("special07"); }
void Map00::special08() { warning("special08"); }
void Map00::special09() { warning("special09"); }
@@ -124,12 +133,48 @@ void Map00::special14() { warning("special14"); }
void Map00::special15() { warning("special15"); }
void Map00::special16() { warning("special16"); }
void Map00::special17() { warning("special17"); }
-void Map00::special18() { warning("special18"); }
-void Map00::special19() { warning("special19"); }
-void Map00::special20() { warning("special20"); }
-void Map00::special21() { warning("special21"); }
-void Map00::special22() { warning("special22"); }
-void Map00::special23() { warning("special23"); }
+
+void Map00::special18() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ 2, 0, STRING["maps.map00.sign"],
+ 6, 1, STRING["maps.map00.temple"]
+ ));
+}
+
+void Map00::special19() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ 2, 0, STRING["maps.map00.sign"],
+ 6, 1, STRING["maps.map00.jail"]
+ ));
+}
+
+void Map00::special20() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ 2, 0, STRING["maps.map00.sign"],
+ 6, 1, STRING["maps.map00.tavern"]
+ ));
+}
+void Map00::special21() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ 2, 0, STRING["maps.map00.sign"],
+ 6, 1, STRING["maps.map00.training"]
+ ));
+}
+
+void Map00::special22() {
+ Map &map = *g_maps->_currentMap;
+ map[0x2f] = 3;
+ map[0x21] = 6;
+ g_maps->clearSpecial();
+}
+
+void Map00::special23() {
+ warning("special23");
+}
} // namespace Maps
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/tavern.h b/engines/mm/mm1/views/businesses/tavern.h
index 73c54f92774..9625f824322 100644
--- a/engines/mm/mm1/views/businesses/tavern.h
+++ b/engines/mm/mm1/views/businesses/tavern.h
@@ -30,8 +30,6 @@ namespace Views {
namespace Businesses {
class Tavern : public Business {
-private:
- int _val1 = 0;
private:
/**
* Have a drink
diff --git a/engines/mm/mm1/views/businesses/temple.cpp b/engines/mm/mm1/views/businesses/temple.cpp
new file mode 100644
index 00000000000..f278dbbafd6
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/temple.cpp
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/businesses/temple.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+Temple::Temple() : Business("Temple") {
+ _modeString = STRING["dialogs.business.gather"];
+}
+
+bool Temple::msgFocus(const FocusMessage &msg) {
+ g_events->msgBusiness(BusinessMessage(2));
+ g_globals->_currCharacter = &g_globals->_party[0];
+ return true;
+}
+
+bool Temple::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ leave();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Temple::draw() {
+ Business::draw();
+}
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/temple.h b/engines/mm/mm1/views/businesses/temple.h
new file mode 100644
index 00000000000..6f678d5408c
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/temple.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_BUSINESSES_TEMPLE_H
+#define MM1_VIEWS_BUSINESSES_TEMPLE_H
+
+#include "mm/mm1/views/businesses/business.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+class Temple : public Business {
+private:
+
+public:
+ Temple();
+ virtual ~Temple() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void draw() override;
+};
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index a81742796c0..78f5273de9f 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -34,6 +34,7 @@
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
#include "mm/mm1/views/businesses/tavern.h"
+#include "mm/mm1/views/businesses/temple.h"
namespace MM {
namespace MM1 {
@@ -53,6 +54,7 @@ private:
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
Views::Businesses::Tavern _tavern;
+ Views::Businesses::Temple _temple;
public:
Dialogs() {}
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index d6ddf196c23..0a7978b7b48 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -203,7 +203,7 @@ void GameView::drawDialogMessage() {
void GameView::drawBusinessName() {
writeString(10, 15, STRING[Common::String::format(
- "maps.businesses.%d", _businessDisplay)]);
+ "dialogs.business.titles.%d", _businessDisplay)]);
_businessDisplay = -1;
}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 0d993473ee4..aa2f5d62b44 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -23,6 +23,7 @@ MODULE_OBJS := \
mm1/utils/strings.o \
mm1/views/businesses/business.o \
mm1/views/businesses/tavern.o \
+ mm1/views/businesses/temple.o \
mm1/views/are_you_ready.o \
mm1/views/create_characters.o \
mm1/views/game.o \
Commit: fd25f5e0a6ef81fea07a570d6c0b832acbc5fe2c
https://github.com/scummvm/scummvm/commit/fd25f5e0a6ef81fea07a570d6c0b832acbc5fe2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:53+01:00
Commit Message:
MM: MM1: Standardize Eulard sign string id to market
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map00.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 619b775a884..8321a906ebd 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -502,7 +502,7 @@ maps:
temple: "TEMPLE MOONSHADOW"
training: "OTTO'S TRAINING"
jail: "JAIL. KEEP OUT!"
- eulards: """EULARDS FINE FOODS"""
+ market: """EULARDS FINE FOODS"""
blacksmith: """B AND B BLACKSMITHING"""
inn: """THE INN OF SORPIGAL"""
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 286731a2ba4..fa4eb43855f 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -60,7 +60,7 @@ void Map00::special01() {
switch (g_maps->_forwardMask) {
case DIRMASK_E:
- line2 = STRING["maps.map00.eulards"];
+ line2 = STRING["maps.map00.market"];
x = 6;
break;
case DIRMASK_W:
Commit: ca857e1d62af60f0c2a5d66d263f6fab90491caf
https://github.com/scummvm/scummvm/commit/ca857e1d62af60f0c2a5d66d263f6fab90491caf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:53+01:00
Commit Message:
MM: MM1: Initial template display
Changed paths:
A engines/mm/mm1/data/items.cpp
A engines/mm/mm1/data/items.h
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/globals.h
engines/mm/mm1/views/businesses/temple.cpp
engines/mm/mm1/views/businesses/temple.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 3bc4d91701b..289d27d0db5 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -28,7 +28,7 @@ namespace MM1 {
void Character::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
s.syncAsByte(_sex);
- s.syncAsByte(_field11);
+ s.syncAsByte(_alignmentInitial);
s.syncAsByte(_alignment);
s.syncAsByte(_race);
s.syncAsByte(_class);
@@ -76,6 +76,7 @@ void Character::synchronize(Common::Serializer &s) {
void Character::clear() {
Common::fill(_name, _name + 16, 0);
_sex = (Sex)0;
+ _alignmentInitial = (Alignment)0;
_alignment = (Alignment)0;
_race = (Race)0;
_class = (CharacterClass)0;
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index a0e89631cf3..6659c797e11 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -62,6 +62,7 @@ struct Character {
char _name[16] = { 0 };
Sex _sex = MALE;
int _field11 = 0;
+ Alignment _alignmentInitial = GOOD;
Alignment _alignment = GOOD;
Race _race = HUMAN;
CharacterClass _class = NONE;
diff --git a/engines/mm/mm1/data/items.cpp b/engines/mm/mm1/data/items.cpp
new file mode 100644
index 00000000000..5f37b7561b3
--- /dev/null
+++ b/engines/mm/mm1/data/items.cpp
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/items.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+
+const Item ITEMS1[] = {
+ { 0 }
+};
+
+const Item ITEMS2[] = {
+ { 0 }
+};
+
+Item *getItem(byte index) {
+ g_globals->_currItem = (index >= 86) ?
+ ITEMS1[index - 1] : ITEMS2[index - 86];
+ g_globals->_currItem._name = STRING[Common::String::format(
+ "stats.items.%d", (int)index)];
+
+ return &g_globals->_currItem;
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
new file mode 100644
index 00000000000..6ba110ba240
--- /dev/null
+++ b/engines/mm/mm1/data/items.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_ITEMS_H
+#define MM1_DATA_ITEMS_H
+
+#include "common/str.h"
+
+namespace MM {
+namespace MM1 {
+
+struct Item {
+ Common::String _name;
+ byte _field10;
+};
+
+extern const Item ITEMS1[];
+extern const Item ITEMS2[];
+
+extern Item *getItem(byte index);
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 882aa37363f..69707553d58 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -27,6 +27,7 @@
#include "mm/utils/strings_data.h"
#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/int_array.h"
+#include "mm/mm1/data/items.h"
#include "mm/mm1/data/roster.h"
#include "mm/mm1/maps/maps.h"
@@ -38,6 +39,7 @@ public:
StringsData _strings;
Roster _roster;
Character *_currCharacter = nullptr;
+ Item _currItem;
Maps::TownId _startingTown = Maps::SORPIGAL;
IntArray _partyChars;
Maps::Maps _maps;
diff --git a/engines/mm/mm1/views/businesses/temple.cpp b/engines/mm/mm1/views/businesses/temple.cpp
index f278dbbafd6..b4ef287cf0c 100644
--- a/engines/mm/mm1/views/businesses/temple.cpp
+++ b/engines/mm/mm1/views/businesses/temple.cpp
@@ -30,13 +30,21 @@ namespace MM1 {
namespace Views {
namespace Businesses {
+static const uint16 HEAL_COST1[5] = { 2000, 5000, 5000, 2000, 8000 };
+static const uint16 HEAL_COST2[5] = { 200, 500, 500, 200, 1000 };
+static const uint16 HEAL_COST3[5] = { 25, 50, 50, 25, 100 };
+static const uint16 UNCURSE_COST[5] = { 500, 1000, 1000, 1012, 1500 };
+static const uint16 ALIGNMENT_COST[5] = { 250, 200, 200, 200, 250 };
+static const uint16 DONATE_COST[5] = { 100, 100, 100, 25, 200 };
+
Temple::Temple() : Business("Temple") {
_modeString = STRING["dialogs.business.gather"];
}
bool Temple::msgFocus(const FocusMessage &msg) {
g_events->msgBusiness(BusinessMessage(2));
- g_globals->_currCharacter = &g_globals->_party[0];
+ selectCharacter(0);
+
return true;
}
@@ -52,8 +60,81 @@ bool Temple::msgKeypress(const KeypressMessage &msg) {
return true;
}
+void Temple::selectCharacter(uint charIndex) {
+ Maps::Map &map = *g_maps->_currentMap;
+ int i;
+
+ g_globals->_currCharacter = &g_globals->_party[charIndex];
+ _isEradicated = false;
+
+ int townNum = map[0];
+ if (townNum < 1 || townNum >= 6)
+ townNum = 1;
+ --townNum;
+ /*
+ _healCost = HEAL_COST[townNum];
+ _uncurseCost = UNCURSE_COST[townNum];
+ _donateCost = DONATE_COST[townNum];
+ */
+
+ Character &c = *g_globals->_currCharacter;
+
+ _healCost = 0;
+ if (c._condition == ERADICATED) {
+ _healCost = HEAL_COST1[townNum];
+ _isEradicated = true;
+ } else if (c._condition & BAD_CONDITION) {
+ _healCost = HEAL_COST2[townNum];
+ } else if (c._condition || c._hp < c._hpMax) {
+ _healCost = HEAL_COST3[townNum];
+ }
+
+ _uncurseCost = UNCURSE_COST[townNum];
+ for (i = 0; i < INVENTORY_COUNT; ++i) {
+ if (c._equipped[i]) {
+ if (getItem(c._equipped[i])->_field10 == 0xff)
+ break;
+ }
+ }
+ if (i == INVENTORY_COUNT)
+ _uncurseCost = 0;
+
+ _alignmentCost = ALIGNMENT_COST[townNum];
+ if (c._alignment == c._alignmentInitial)
+ _alignmentCost = 0;
+
+ _donateCost = DONATE_COST[townNum];
+}
+
void Temple::draw() {
Business::draw();
+
+ writeString(21, 0, STRING["dialogs.temple.service_cost"]);
+
+ writeString(18, 2, STRING["dialogs.temple.a"]);
+ _textPos.x = 36;
+ if (_healCost)
+ writeNumber(_healCost);
+ else
+ writeString("----");
+
+ writeString(18, 3, STRING["dialogs.temple.b"]);
+ _textPos.x = 36;
+ if (_uncurseCost)
+ writeNumber(_uncurseCost);
+ else
+ writeString("----");
+
+ writeString(18, 4, STRING["dialogs.temple.c"]);
+ _textPos.x = 36;
+ if (_alignmentCost)
+ writeNumber(_alignmentCost);
+ else
+ writeString("----");
+
+ writeString(18, 5, STRING["dialogs.temple.d"]);
+ _textPos.x = 36;
+ writeNumber(_donateCost);
}
} // namespace Businesses
diff --git a/engines/mm/mm1/views/businesses/temple.h b/engines/mm/mm1/views/businesses/temple.h
index 6f678d5408c..93e8ba1675c 100644
--- a/engines/mm/mm1/views/businesses/temple.h
+++ b/engines/mm/mm1/views/businesses/temple.h
@@ -31,7 +31,14 @@ namespace Businesses {
class Temple : public Business {
private:
-
+ bool _isEradicated = false;
+ int _healCost = 0, _uncurseCost = 0;
+ int _alignmentCost = 0, _donateCost = 0;
+
+ /**
+ * Selects a character
+ */
+ void selectCharacter(uint charIndex);
public:
Temple();
virtual ~Temple() {}
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 2ada2f1c4de..aac1ebb3ea1 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -69,7 +69,7 @@ void CreateCharacters::NewCharacter::save() {
Common::strcpy_s(re._name, _name.c_str());
re._sex = _sex;
- re._alignment = _alignment;
+ re._alignment = re._alignmentInitial = _alignment;
re._race = _race;
re._class = _class;
re._int = _attribs1[INTELLECT];
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index aa2f5d62b44..471234f016a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
mm1/sound.o \
mm1/data/char.o \
mm1/data/game_state.o \
+ mm1/data/items.o \
mm1/data/roster.o \
mm1/game/search.o \
mm1/game/view_base.o \
Commit: dd233a50fa9fddddbe9f9b21a7f45c3579047095
https://github.com/scummvm/scummvm/commit/dd233a50fa9fddddbe9f9b21a7f45c3579047095
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:53+01:00
Commit Message:
MM: MM1: Implement remainder of Temple
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.h
engines/mm/mm1/data/items.cpp
engines/mm/mm1/sound.h
engines/mm/mm1/views/businesses/business.cpp
engines/mm/mm1/views/businesses/business.h
engines/mm/mm1/views/businesses/tavern.cpp
engines/mm/mm1/views/businesses/tavern.h
engines/mm/mm1/views/businesses/temple.cpp
engines/mm/mm1/views/businesses/temple.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 8321a906ebd..8af8ad3e8fa 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -144,6 +144,8 @@ dialogs:
b: "B) UNCURSE ITEMS"
c: "C) RESTORE ALIGN"
d: "D) MAKE DONATION"
+ thankyou: "THANK YOU!"
+ protected: "*** TODAY YOU SHALL BE PROTECTED!"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 6659c797e11..5ee16df8340 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -68,6 +68,7 @@ struct Character {
CharacterClass _class = NONE;
uint8 _int = 0, _mgt = 0, _per = 0, _end = 0;
uint8 _spd = 0, _acy = 0, _luc = 0;
+ uint8 _end2 = 0;
uint8 _level = 0;
uint8 _age = 0;
uint32 _exp = 0;
@@ -84,7 +85,7 @@ struct Character {
// TODO: Figure out what these are
int _v58, _v59, _v62, _v63, _v64, _v65;
- int _v66, _v67, _v6c, _v6f;
+ int _v66, _v67, _v6c, _v6e, _v6f;
// Non persistent fields
byte _numDrinks = 0;
diff --git a/engines/mm/mm1/data/items.cpp b/engines/mm/mm1/data/items.cpp
index 5f37b7561b3..6e54815daa3 100644
--- a/engines/mm/mm1/data/items.cpp
+++ b/engines/mm/mm1/data/items.cpp
@@ -25,7 +25,93 @@
namespace MM {
namespace MM1 {
-const Item ITEMS1[] = {
+// TODO: Figure out all item fields
+const Item ITEMS1[86] = {
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
+ { 0 },
{ 0 }
};
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
index 3b0340a4643..34e578d8846 100644
--- a/engines/mm/mm1/sound.h
+++ b/engines/mm/mm1/sound.h
@@ -25,7 +25,7 @@
namespace MM {
namespace MM1 {
-enum SoundId { SOUND_1 = 1, SOUND_2 = 2 };
+enum SoundId { SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3 };
class Sound {
public:
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/businesses/business.cpp
index 04128a2eda8..df75d797747 100644
--- a/engines/mm/mm1/views/businesses/business.cpp
+++ b/engines/mm/mm1/views/businesses/business.cpp
@@ -59,6 +59,16 @@ void Business::newLine() {
_textPos.y = 0;
}
+void Business::gatherGold() {
+ uint total = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ total += g_globals->_party[i]._gold;
+ g_globals->_party[i]._gold = 0;
+ }
+
+ g_globals->_currCharacter->_gold = total;
+}
+
bool Business::subtractGold(uint amount) {
if (g_globals->_currCharacter->_gold < amount) {
notEnoughGold();
@@ -74,6 +84,14 @@ void Business::notEnoughGold() {
displayMessage(STRING["dialogs.misc.not_enough_gold"]);
}
+void Business::changeCharacter(uint index) {
+ if (index >= g_globals->_party.size())
+ return;
+
+ g_globals->_currCharacter = &g_globals->_party[index];
+ redraw();
+}
+
void Business::leave() {
SWAP(g_maps->_forwardMask, g_maps->_backwardsMask);
SWAP(g_maps->_leftMask, g_maps->_rightMask);
diff --git a/engines/mm/mm1/views/businesses/business.h b/engines/mm/mm1/views/businesses/business.h
index a67d5bd2aa9..9bac4345c6d 100644
--- a/engines/mm/mm1/views/businesses/business.h
+++ b/engines/mm/mm1/views/businesses/business.h
@@ -54,6 +54,11 @@ protected:
*/
void leave();
+ /**
+ * Gathers all the party gold to the current character
+ */
+ void gatherGold();
+
/**
* Subtract gold from current character
*/
@@ -63,6 +68,11 @@ protected:
* Displays not enough gold
*/
void notEnoughGold();
+
+ /**
+ * Change character
+ */
+ virtual void changeCharacter(uint index);
public:
Business(const Common::String &name);
virtual ~Business() {}
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
index 1d0fe5d4df1..38924e3d566 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -63,14 +63,9 @@ bool Tavern::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_3:
case Common::KEYCODE_4:
case Common::KEYCODE_5:
- case Common::KEYCODE_6: {
- uint charIndex = msg.keycode - Common::KEYCODE_1;
- if (charIndex < g_globals->_party.size()) {
- g_globals->_currCharacter = &g_globals->_party[charIndex];
- redraw();
- }
+ case Common::KEYCODE_6:
+ changeCharacter(msg.keycode - Common::KEYCODE_1);
break;
- }
default:
break;
}
@@ -135,16 +130,6 @@ void Tavern::listenForRumors() {
displayMessage(msg);
}
-void Tavern::gatherGold() {
- uint total = 0;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- total += g_globals->_party[i]._gold;
- g_globals->_party[i]._gold = 0;
- }
-
- g_globals->_currCharacter->_gold = total;
-}
-
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/tavern.h b/engines/mm/mm1/views/businesses/tavern.h
index 9625f824322..003b4697df7 100644
--- a/engines/mm/mm1/views/businesses/tavern.h
+++ b/engines/mm/mm1/views/businesses/tavern.h
@@ -46,11 +46,6 @@ private:
*/
void listenForRumors();
- /**
- * Gathers all the party gold to the current character
- */
- void gatherGold();
-
public:
Tavern();
virtual ~Tavern() {}
diff --git a/engines/mm/mm1/views/businesses/temple.cpp b/engines/mm/mm1/views/businesses/temple.cpp
index b4ef287cf0c..5568681a900 100644
--- a/engines/mm/mm1/views/businesses/temple.cpp
+++ b/engines/mm/mm1/views/businesses/temple.cpp
@@ -36,6 +36,8 @@ static const uint16 HEAL_COST3[5] = { 25, 50, 50, 25, 100 };
static const uint16 UNCURSE_COST[5] = { 500, 1000, 1000, 1012, 1500 };
static const uint16 ALIGNMENT_COST[5] = { 250, 200, 200, 200, 250 };
static const uint16 DONATE_COST[5] = { 100, 100, 100, 25, 200 };
+static const byte ALIGNMENT_VALS[3] = { 8, 0x10, 0x18 };
+static const byte DONATE_VALS[5] = { 1, 2, 4, 8, 0x10 };
Temple::Temple() : Business("Temple") {
_modeString = STRING["dialogs.business.gather"];
@@ -43,7 +45,7 @@ Temple::Temple() : Business("Temple") {
bool Temple::msgFocus(const FocusMessage &msg) {
g_events->msgBusiness(BusinessMessage(2));
- selectCharacter(0);
+ changeCharacter(0);
return true;
}
@@ -53,6 +55,30 @@ bool Temple::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_ESCAPE:
leave();
break;
+ case Common::KEYCODE_a:
+ restoreHealth();
+ break;
+ case Common::KEYCODE_b:
+ uncurseItems();
+ break;
+ case Common::KEYCODE_c:
+ restoreAlignment();
+ break;
+ case Common::KEYCODE_d:
+ donate();
+ break;
+ case Common::KEYCODE_g:
+ gatherGold();
+ redraw();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ changeCharacter(msg.keycode - Common::KEYCODE_1);
+ break;
default:
break;
}
@@ -60,22 +86,20 @@ bool Temple::msgKeypress(const KeypressMessage &msg) {
return true;
}
-void Temple::selectCharacter(uint charIndex) {
+void Temple::changeCharacter(uint index) {
Maps::Map &map = *g_maps->_currentMap;
int i;
- g_globals->_currCharacter = &g_globals->_party[charIndex];
+ if (index >= g_globals->_party.size())
+ return;
+ Business::changeCharacter(index);
+
_isEradicated = false;
int townNum = map[0];
if (townNum < 1 || townNum >= 6)
townNum = 1;
--townNum;
- /*
- _healCost = HEAL_COST[townNum];
- _uncurseCost = UNCURSE_COST[townNum];
- _donateCost = DONATE_COST[townNum];
- */
Character &c = *g_globals->_currCharacter;
@@ -137,6 +161,72 @@ void Temple::draw() {
writeNumber(_donateCost);
}
+void Temple::restoreHealth() {
+ if (subtractGold(_healCost)) {
+ Character &c = *g_globals->_currCharacter;
+ c._condition = FINE;
+ c._hp = c._hp2;
+
+ if (_isEradicated) {
+ c._age += 10;
+ if (c._end2)
+ c._end = --c._end2;
+ }
+
+ redraw();
+ }
+}
+
+void Temple::uncurseItems() {
+ if (subtractGold(_uncurseCost)) {
+ Character &c = *g_globals->_currCharacter;
+ for (int i = 0; i < INVENTORY_COUNT; ++i) {
+ if (c._equipped[i]) {
+ getItem(c._equipped[i]);
+ if (c._field11 == 0xff)
+ c._equipped[i] = 0;
+ }
+ }
+
+ redraw();
+ }
+}
+
+void Temple::restoreAlignment() {
+ if (subtractGold(_alignmentCost)) {
+ Character &c = *g_globals->_currCharacter;
+ c._alignment = c._alignmentInitial;
+ c._v6f = ALIGNMENT_VALS[c._alignment];
+
+ redraw();
+ }
+}
+
+void Temple::donate() {
+ if (subtractGold(_donateCost)) {
+ Maps::Map &map = *g_maps->_currentMap;
+ Character &c = *g_globals->_currCharacter;
+
+ int townNum = map[0];
+ if (townNum < 1 || townNum >= 6)
+ townNum = 1;
+ --townNum;
+
+ c._v6e |= DONATE_VALS[townNum];
+ draw();
+
+ if (g_engine->getRandomNumber(15) == 10) {
+ for (int i = 0; i < 13; ++i)
+ g_globals->_spells._arr[i] = 75;
+
+ Sound::sound(SOUND_3);
+ displayMessage(STRING["dialogs.temple.protected"]);
+ } else {
+ displayMessage(STRING["dialogs.temple.thankyou"]);
+ }
+ }
+}
+
} // namespace Businesses
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/businesses/temple.h b/engines/mm/mm1/views/businesses/temple.h
index 93e8ba1675c..3c0671d575f 100644
--- a/engines/mm/mm1/views/businesses/temple.h
+++ b/engines/mm/mm1/views/businesses/temple.h
@@ -34,11 +34,18 @@ private:
bool _isEradicated = false;
int _healCost = 0, _uncurseCost = 0;
int _alignmentCost = 0, _donateCost = 0;
+private:
+ void restoreHealth();
+ void uncurseItems();
+ void restoreAlignment();
+ void donate();
+protected:
/**
- * Selects a character
+ * Change character
*/
- void selectCharacter(uint charIndex);
+ void changeCharacter(uint index) override;
+
public:
Temple();
virtual ~Temple() {}
Commit: 44cf0b55d11e44b8e4afb0f3eb5e5431f9782508
https://github.com/scummvm/scummvm/commit/44cf0b55d11e44b8e4afb0f3eb5e5431f9782508
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:53+01:00
Commit Message:
MM: MM1: Added market view
Changed paths:
A engines/mm/mm1/views/businesses/market.cpp
A engines/mm/mm1/views/businesses/market.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 8af8ad3e8fa..e6541f216ef 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -48,6 +48,12 @@ dialogs:
option3: "'#'.......GO TO TOWN"
copyright1: "COPR. 1986,1987-JON VAN CANEGHEM"
copyright2: "ALL RIGHTS RESERVED"
+ market:
+ special: "SPECIAL TODAY,ALL YOU CAN EAT! "
+ gp: "GP/EA"
+ will_you_pay: "WILL YOU PAY (Y/N)?"
+ thankyou: "THANK YOU, COME AGAIN!"
+ no_gold: "NO GOLD, NO FOOD!"
order:
title: " RE-ORDER PARTY NEW 1 2 3 4 5 6"
old: "OLD"
@@ -500,22 +506,21 @@ stats:
maps:
map00:
sign: "A SIGN ABOVE THE DOOR READS: "
+ blacksmith: """B AND B BLACKSMITHING"""
+ inn: """THE INN OF SORPIGAL"""
+ jail: "JAIL. KEEP OUT!"
+ market: """EULARDS FINE FOODS"""
tavern: "YE OLDE HOGGE TAVERN"
temple: "TEMPLE MOONSHADOW"
training: "OTTO'S TRAINING"
- jail: "JAIL. KEEP OUT!"
- market: """EULARDS FINE FOODS"""
- blacksmith: """B AND B BLACKSMITHING"""
- inn: """THE INN OF SORPIGAL"""
+ blacksmith_inside: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
+ inn_inside: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
+ market_inside: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
tavern_inside: "STEP UP TO THE BAR (Y/N)?"
- temple_inside: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
+ temple_inside: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
+ training_inside: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
- c9d3: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
- ca69: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
- food: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
-
- cbc8: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
cd2e: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
cd53: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index fa4eb43855f..a9a94030c7e 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -80,15 +80,13 @@ void Map00::special01() {
void Map00::special02() { warning("special02"); }
void Map00::special03() {
- /*
Sound::sound(SOUND_2);
g_events->msgInfo(InfoMessage(
- STRING["maps.map00.food"],
+ STRING["maps.map00.market_inside"],
[]() {
-
+ g_events->addView("MARKET");
}
));
- */
}
void Map00::special04() {
diff --git a/engines/mm/mm1/views/businesses/market.cpp b/engines/mm/mm1/views/businesses/market.cpp
new file mode 100644
index 00000000000..b5cdc3da4c9
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/market.cpp
@@ -0,0 +1,113 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/businesses/market.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+#define TOTAL_FOOD 40
+#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
+
+static const byte FOOD_COST[4] = { 5, 10, 20, 200 };
+
+Market::Market() : Business("Market") {
+ _bounds = getLineBounds(21, 24);
+}
+
+bool Market::msgFocus(const FocusMessage &msg) {
+ g_events->msgBusiness(BusinessMessage(1));
+
+ Maps::Map &map = *g_maps->_currentMap;
+ _foodCost = FOOD_COST[map[0] - 1];
+
+ return true;
+}
+
+bool Market::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_n:
+ leave();
+ break;
+ case Common::KEYCODE_y:
+ if (!_displayCtr)
+ buyFood();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Market::draw() {
+ clearSurface();
+
+ writeString(0, 0, STRING["dialogs.market.special"]);
+ writeNumber(_foodCost);
+ writeString(STRING["dialogs.market.gp"]);
+ writeString(10, 2, STRING["dialogs.market.will_you_pay"]);
+}
+
+bool Market::tick() {
+ if (_displayCtr && --_displayCtr == 0)
+ leave();
+ return false;
+}
+
+void Market::buyFood() {
+ int foodPurchased = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (buyFood(&g_globals->_party[i]))
+ ++foodPurchased;
+ }
+
+ clearSurface();
+ writeString(10, 2, foodPurchased ?
+ STRING["dialogs.market.thankyou"] :
+ STRING["dialogs.market.no_gold"]
+ );
+
+ _displayCtr = DISPLAY_TIMEOUT;
+}
+
+bool Market::buyFood(Character *c) {
+ int tempGold = (int)c->_gold - _foodCost;
+ if (tempGold < 0)
+ return false;
+
+ c->_gold = tempGold;
+ c->_food = TOTAL_FOOD;
+
+ return true;
+}
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/market.h b/engines/mm/mm1/views/businesses/market.h
new file mode 100644
index 00000000000..2a50081991c
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/market.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_BUSINESSES_MARKET_H
+#define MM1_VIEWS_BUSINESSES_MARKET_H
+
+#include "mm/mm1/data/char.h"
+#include "mm/mm1/views/businesses/business.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+class Market : public Business {
+private:
+ int _foodCost = 0;
+ int _displayCtr = 0;
+private:
+ /**
+ * Buys food
+ */
+ void buyFood();
+
+ /**
+ * Has a single character buy food
+ */
+ bool buyFood(Character *c);
+public:
+ Market();
+ virtual ~Market() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void draw() override;
+ bool tick() override;
+};
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 78f5273de9f..f097983e589 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -33,6 +33,7 @@
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/views/businesses/market.h"
#include "mm/mm1/views/businesses/tavern.h"
#include "mm/mm1/views/businesses/temple.h"
@@ -53,6 +54,7 @@ private:
Views::Title _title;
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
+ Views::Businesses::Market _market;
Views::Businesses::Tavern _tavern;
Views::Businesses::Temple _temple;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 471234f016a..86bcb6d3721 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -23,6 +23,7 @@ MODULE_OBJS := \
mm1/gfx/screen_decoder.o \
mm1/utils/strings.o \
mm1/views/businesses/business.o \
+ mm1/views/businesses/market.o \
mm1/views/businesses/tavern.o \
mm1/views/businesses/temple.o \
mm1/views/are_you_ready.o \
Commit: 22f8cde89a4a7124b6fe34a4fa0f353fc714d351
https://github.com/scummvm/scummvm/commit/22f8cde89a4a7124b6fe34a4fa0f353fc714d351
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:53+01:00
Commit Message:
MM: MM1: Display of Xeen UI buttons in enhanced mode
Changed paths:
A engines/mm/mm1/views_enh/button_container.cpp
A engines/mm/mm1/views_enh/button_container.h
A engines/mm/mm1/views_enh/game_commands.cpp
A engines/mm/mm1/views_enh/game_commands.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/messages.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/views_enh/game.cpp
engines/mm/mm1/views_enh/game.h
engines/mm/module.mk
engines/mm/xeen/sprites.cpp
engines/mm/xeen/sprites.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index b80c72e0251..328317d83f2 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -88,6 +88,11 @@ void Events::processEvent(Common::Event &ev) {
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
msgAction(ActionMessage((KeybindingAction)ev.customType));
break;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ //case Common::EVENT_MBUTTONUP:
+ msgMouseClick(MouseClickMessage(ev.type, ev.mouse));
+ break;
default:
break;
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 747f5ab708d..81372f37256 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -133,6 +133,7 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
+ MESSAGE(MouseClick);
MESSAGE(Action);
MESSAGE(Business);
MESSAGE(Game);
@@ -208,6 +209,7 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
+ MESSAGE(MouseClick);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 5dccd18fce8..54c5f6b17f2 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -38,7 +38,7 @@ Globals::~Globals() {
g_globals = nullptr;
}
-bool Globals::load() {
+bool Globals::load(bool isEnhanced) {
// Initialise engine data for the game
Common::U32String errMsg;
if (!load_engine_data("mm1", 1, 0, errMsg)) {
@@ -55,6 +55,10 @@ bool Globals::load() {
// Load roster
_roster.load();
+ if (isEnhanced) {
+ _mainIcons.load("main.icn");
+ }
+
return true;
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 69707553d58..f474ff0c475 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -25,6 +25,7 @@
#include "graphics/font.h"
#include "mm/utils/bitmap_font.h"
#include "mm/utils/strings_data.h"
+#include "mm/xeen/sprites.h"
#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/int_array.h"
#include "mm/mm1/data/items.h"
@@ -46,6 +47,9 @@ public:
bool _intangible = false; // Console flag
BitmapFont _font;
bool _heardRumor = false;
+public:
+ // Enhanced mode globals
+ Xeen::SpriteResource _mainIcons;
public:
Globals();
virtual ~Globals();
@@ -53,7 +57,7 @@ public:
/**
* Loads data for the globals
*/
- bool load();
+ bool load(bool isEnhanced);
/**
* Returns a string
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
index 265e1e7c537..7d29be5f242 100644
--- a/engines/mm/mm1/messages.cpp
+++ b/engines/mm/mm1/messages.cpp
@@ -24,6 +24,21 @@
namespace MM {
namespace MM1 {
+MouseClickMessage::MouseClickMessage(Common::EventType type,
+ const Common::Point &pos) : Message() {
+ switch (type) {
+ case Common::EVENT_RBUTTONUP:
+ _button = MB_RIGHT;
+ break;
+ case Common::EVENT_MBUTTONUP:
+ _button = MB_MIDDLE;
+ break;
+ default:
+ _button = MB_LEFT;
+ break;
+ }
+}
+
InfoMessage::InfoMessage() : Message(), _ynCallback(nullptr) {}
InfoMessage::InfoMessage(const Common::String &str,
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index cea5a7e57a2..3040c52f916 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -46,6 +46,17 @@ struct KeypressMessage : public Message, public Common::KeyState {
Message(), Common::KeyState(ks) {}
};
+struct MouseClickMessage : public Message {
+ enum Button { MB_LEFT, MB_RIGHT, MB_MIDDLE };
+ Button _button;
+ Common::Point _pos;
+
+ MouseClickMessage() : Message(), _button(MB_LEFT) {}
+ MouseClickMessage(Button btn, const Common::Point &pos) :
+ Message(), _button(btn), _pos(pos) {}
+ MouseClickMessage(Common::EventType type, const Common::Point &pos);
+};
+
struct GameMessage : public Message {
Common::String _name;
GameMessage() : Message() {}
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index e87b61f737b..6f851698054 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -61,7 +61,7 @@ Common::Error MM1Engine::run() {
setDebugger(new Console());
// Load globals
- if (!_globals.load())
+ if (!_globals.load(isEnhanced()))
return Common::kNoError;
runGame();
@@ -84,24 +84,28 @@ void MM1Engine::setupNormal() {
}
bool MM1Engine::setupEnhanced() {
- if (!Common::File::exists("dark.cc")) {
+ if (!Common::File::exists("xeen.cc")) {// || !Common::File::exists("dark.cc")) {
GUIErrorMessage(
- "In order to run in Enhanced mode, please copy dark.cc "
- "from a copy of World of Xeen\n"
+ "In order to run in Enhanced mode, please copy xeen.cc "
+ "and dark.cc from a copy of World of Xeen\n"
"or Dark Side of Xeen to your Might and Magic 1 game folder"
);
return false;
}
- // Add the Dark Side dark.cc archive
+ // Add the Xeen cc archives
+ ::MM::Xeen::CCArchive *xeenCC = new ::MM::Xeen::CCArchive(
+ "xeen.cc", "xeen", true);
+ SearchMan.add("xeen", xeenCC);
+ /*
::MM::Xeen::CCArchive *darkCC = new ::MM::Xeen::CCArchive(
"dark.cc", "dark", true);
SearchMan.add("dark", darkCC);
-
+ */
// Load the palette
Common::File f;
- if (!f.open("dark.pal"))
+ if (!f.open("mm4.pal"))
error("Could not load palette");
byte pal[PALETTE_SIZE];
diff --git a/engines/mm/mm1/views_enh/button_container.cpp b/engines/mm/mm1/views_enh/button_container.cpp
new file mode 100644
index 00000000000..30357da636c
--- /dev/null
+++ b/engines/mm/mm1/views_enh/button_container.cpp
@@ -0,0 +1,111 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "mm/mm1/views_enh/button_container.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+void UIButton::draw(bool pressed) {
+ _sprites->draw(g_events->getScreen(),
+ pressed ? _selectedFrame : _frameNum,
+ Common::Point(_bounds.left, _bounds.top));
+}
+
+ButtonContainer::ButtonContainer(const Common::String &name,
+ UIElement *owner) : Views::TextView(name, owner),
+ _buttonValue(0) {
+}
+
+void ButtonContainer::saveButtons() {
+ _savedButtons.push(_buttons);
+ clearButtons();
+}
+
+void ButtonContainer::clearButtons() {
+ _buttons.clear();
+}
+
+void ButtonContainer::restoreButtons() {
+ _buttons = _savedButtons.pop();
+}
+
+void ButtonContainer::addButton(const Common::Rect &bounds, int val,
+ Xeen::SpriteResource *sprites) {
+ _buttons.push_back(UIButton(this, bounds, val, _buttons.size() * 2, sprites, sprites != nullptr));
+}
+
+void ButtonContainer::addButton(const Common::Rect &bounds, int val,
+ int frameNum, Xeen::SpriteResource *sprites) {
+ _buttons.push_back(UIButton(this, bounds, val, frameNum, sprites, sprites != nullptr));
+}
+
+bool ButtonContainer::msgMouseClick(const MouseClickMessage &msg) {
+ _buttonValue = 0;
+
+ if (msg._button == MouseClickMessage::MB_LEFT) {
+ const Common::Point pt = msg._pos;
+
+ // Check whether any button is selected
+ for (uint i = 0; i < _buttons.size(); ++i) {
+ if (_buttons[i]._bounds.contains(pt) && _buttons[i]._value) {
+ _buttonValue = _buttons[i]._value;
+
+ // Show the button briefly depressed
+ _buttons[i].draw(true);
+ g_engine->getScreen()->update();
+ g_system->delayMillis(50);
+
+ _buttons[i].draw(false);
+ g_engine->getScreen()->update();
+
+ // Trigger the button action
+ // TODO
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void ButtonContainer::draw() {
+ TextView::draw();
+
+ for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
+ UIButton &btn = _buttons[btnIndex];
+ if (btn._draw)
+ btn.draw();
+ }
+}
+
+bool ButtonContainer::doScroll(bool fadeIn) {
+ // TODO
+ return false;
+}
+
+} // namespace ViewsEnh
+} // End of namespace MM1
+} // End of namespace MM
diff --git a/engines/mm/mm1/views_enh/button_container.h b/engines/mm/mm1/views_enh/button_container.h
new file mode 100644
index 00000000000..b2ca3e577b7
--- /dev/null
+++ b/engines/mm/mm1/views_enh/button_container.h
@@ -0,0 +1,126 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_BUTTON_CONTAINER_H
+#define MM1_VIEWS_ENH_BUTTON_CONTAINER_H
+
+#include "common/array.h"
+#include "common/stack.h"
+#include "common/rect.h"
+#include "mm/xeen/sprites.h"
+#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/events.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class ButtonContainer;
+
+class UIButton {
+public:
+ Common::Rect _bounds;
+ Xeen::SpriteResource *_sprites;
+ int _value;
+ uint _frameNum, _selectedFrame;
+ bool _draw;
+
+ /**
+ * Constructor
+ */
+ UIButton(ButtonContainer *owner, const Common::Rect &bounds,
+ int value, uint frameNum, Xeen::SpriteResource *sprites,
+ bool draw) :
+ _bounds(bounds), _value(value), _frameNum(frameNum),
+ _selectedFrame(frameNum | 1), _sprites(sprites), _draw(draw) {
+ }
+
+ /**
+ * Constructor
+ */
+ UIButton() : _value(0), _frameNum(0), _selectedFrame(0), _sprites(nullptr), _draw(false) {
+ }
+
+ /**
+ * Set the frame
+ */
+ void setFrame(uint frameNum) {
+ _frameNum = frameNum;
+ _selectedFrame = frameNum | 1;
+ }
+
+ /**
+ * Set the frame
+ */
+ void setFrame(uint frameNum, uint selectedFrame) {
+ _frameNum = frameNum;
+ _selectedFrame = selectedFrame;
+ }
+
+ /**
+ * Draw the button
+ */
+ void draw(bool pressed = false);
+};
+
+class ButtonContainer : public Views::TextView {
+private:
+ Common::Stack< Common::Array<UIButton> > _savedButtons;
+protected:
+ Common::Array<UIButton> _buttons;
+ int _buttonValue;
+
+ bool doScroll(bool fadeIn);
+public:
+ ButtonContainer(const Common::String &name, UIElement *owner);
+
+ /**
+ * Saves the current list of buttons
+ */
+ void saveButtons();
+
+ void clearButtons();
+
+ void restoreButtons();
+
+ void addButton(const Common::Rect &bounds, int val,
+ Xeen::SpriteResource *sprites = nullptr);
+ void addButton(const Common::Rect &bounds, int val,
+ int frameNum, Xeen::SpriteResource *sprites = nullptr);
+
+// void addPartyButtons(XeenEngine *vm);
+
+ /**
+ * Clears any currently set button value
+ */
+ void clearEvents() {
+ _buttonValue = 0;
+ }
+
+ void draw() override;
+ bool msgMouseClick(const MouseClickMessage &msg) override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index bc6df1e7a7b..e3477eb8b31 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -29,7 +29,7 @@ namespace MM1 {
namespace ViewsEnh {
Game::Game() : TextView("Game"),
- _view(this) {
+ _view(this), _commands(this) {
_view.setBounds(Common::Rect(8, 15, 224, 130));
}
diff --git a/engines/mm/mm1/views_enh/game.h b/engines/mm/mm1/views_enh/game.h
index 6e48b450847..54232b2d66c 100644
--- a/engines/mm/mm1/views_enh/game.h
+++ b/engines/mm/mm1/views_enh/game.h
@@ -24,6 +24,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/game_view.h"
+#include "mm/mm1/views_enh/game_commands.h"
namespace MM {
namespace MM1 {
@@ -32,6 +33,7 @@ namespace ViewsEnh {
class Game : public Views::TextView {
private:
Views::GameView _view;
+ GameCommands _commands;
public:
Game();
virtual ~Game() {}
diff --git a/engines/mm/mm1/views_enh/game_commands.cpp b/engines/mm/mm1/views_enh/game_commands.cpp
new file mode 100644
index 00000000000..efdbabd7435
--- /dev/null
+++ b/engines/mm/mm1/views_enh/game_commands.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/game_commands.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+GameCommands::GameCommands(UIElement *owner) :
+ ButtonContainer("GameCommands", owner) {
+ Xeen::SpriteResource *spr = &g_globals->_mainIcons;
+ addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_s, spr);
+ addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_c, spr);
+ addButton(Common::Rect(286, 75, 310, 95), Common::KEYCODE_r, spr);
+ addButton(Common::Rect(235, 96, 259, 116), Common::KEYCODE_b, spr);
+ addButton(Common::Rect(260, 96, 284, 116), Common::KEYCODE_d, spr);
+ addButton(Common::Rect(286, 96, 310, 116), Common::KEYCODE_v, spr);
+ addButton(Common::Rect(235, 117, 259, 137), Common::KEYCODE_m, spr);
+ addButton(Common::Rect(260, 117, 284, 137), Common::KEYCODE_i, spr);
+ addButton(Common::Rect(286, 117, 310, 137), Common::KEYCODE_q, spr);
+ addButton(Common::Rect(109, 137, 122, 147), Common::KEYCODE_TAB, spr);
+ addButton(Common::Rect(235, 148, 259, 168), Common::KEYCODE_LEFT, spr);
+ addButton(Common::Rect(260, 148, 284, 168), Common::KEYCODE_UP, spr);
+ addButton(Common::Rect(286, 148, 310, 168), Common::KEYCODE_RIGHT, spr);
+ addButton(Common::Rect(235, 169, 259, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT, spr);
+ addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, spr);
+ addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, spr);
+ addButton(Common::Rect(236, 11, 308, 69), Common::KEYCODE_EQUALS);
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/game_commands.h b/engines/mm/mm1/views_enh/game_commands.h
new file mode 100644
index 00000000000..f23b5259f8d
--- /dev/null
+++ b/engines/mm/mm1/views_enh/game_commands.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_GAME_COMMANDS_H
+#define MM1_VIEWS_ENH_GAME_COMMANDS_H
+
+#include "mm/mm1/views_enh/button_container.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class GameCommands : public ButtonContainer {
+public:
+ GameCommands(UIElement *owner);
+ virtual ~GameCommands() {}
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 86bcb6d3721..6d4c314cdcb 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -41,6 +41,7 @@ MODULE_OBJS := \
mm1/views/title.o \
mm1/views/text_view.o \
mm1/views/view_characters.o \
+ mm1/views_enh/button_container.o \
mm1/views_enh/dialogs.o \
mm1/views_enh/game.o \
mm1/maps/maps.o \
diff --git a/engines/mm/xeen/sprites.cpp b/engines/mm/xeen/sprites.cpp
index 2eec03bebc1..056527f2d89 100644
--- a/engines/mm/xeen/sprites.cpp
+++ b/engines/mm/xeen/sprites.cpp
@@ -81,7 +81,10 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
void SpriteResource::load(const Common::String &filename) {
_filename = filename;
- File f(filename);
+ Common::File f;
+ if (!f.open(filename))
+ error("Could not open - %s", filename.c_str());
+
load(f);
}
@@ -180,6 +183,18 @@ void SpriteResource::draw(int windowIndex, int frame) {
draw((*g_vm->_windows)[windowIndex], frame, Common::Point());
}
+void SpriteResource::draw(Graphics::ManagedSurface *dest, int frame, const Common::Point &destPos) {
+ XSurface tmp;
+ tmp.w = dest->w;
+ tmp.h = dest->h;
+ tmp.pitch = dest->pitch;
+ tmp.format = dest->format;
+ tmp.setPixels(dest->getPixels());
+
+ draw(tmp, frame, destPos);
+}
+
+
Common::Point SpriteResource::getFrameSize(int frame) const {
Common::MemoryReadStream f(_data, _filesize);
Common::Point frameSize;
diff --git a/engines/mm/xeen/sprites.h b/engines/mm/xeen/sprites.h
index 2f0d81838be..5c791f99f3e 100644
--- a/engines/mm/xeen/sprites.h
+++ b/engines/mm/xeen/sprites.h
@@ -156,6 +156,11 @@ public:
*/
void draw(int windowIndex, int frame);
+ /**
+ * Draw the sprite onto a given surface
+ */
+ void draw(Graphics::ManagedSurface *dest, int frame, const Common::Point &destPos);
+
/**
* Gets the size of a sprite
*/
Commit: 4348a0b2d09b3afb54c4f499c17b1169892ce49a
https://github.com/scummvm/scummvm/commit/4348a0b2d09b3afb54c4f499c17b1169892ce49a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:53+01:00
Commit Message:
MM: XEEN: Fix startup crash
Changed paths:
engines/mm/xeen/sprites.cpp
diff --git a/engines/mm/xeen/sprites.cpp b/engines/mm/xeen/sprites.cpp
index 056527f2d89..43e9158944f 100644
--- a/engines/mm/xeen/sprites.cpp
+++ b/engines/mm/xeen/sprites.cpp
@@ -82,10 +82,12 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
void SpriteResource::load(const Common::String &filename) {
_filename = filename;
Common::File f;
- if (!f.open(filename))
- error("Could not open - %s", filename.c_str());
-
- load(f);
+ if (f.open(filename)) {
+ load(f);
+ } else {
+ File f2(filename);
+ load(f2);
+ }
}
void SpriteResource::load(const Common::String &filename, int ccMode) {
Commit: ccc0d5a872a2c37b54f4f07eb9a58a69ca9fcfcd
https://github.com/scummvm/scummvm/commit/ccc0d5a872a2c37b54f4f07eb9a58a69ca9fcfcd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Add mouse cursor in enhanced mode
Changed paths:
A engines/mm/mm1/utils/mouse.cpp
A engines/mm/mm1/utils/mouse.h
engines/mm/mm1/events.h
engines/mm/mm1/mm1.cpp
engines/mm/module.mk
engines/mm/xeen/files.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 81372f37256..afc89877ddd 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -26,6 +26,7 @@
#include "common/stack.h"
#include "graphics/screen.h"
#include "mm/mm1/messages.h"
+#include "mm/mm1/utils/mouse.h"
namespace MM {
namespace MM1 {
@@ -141,7 +142,7 @@ public:
#undef MESSAGE
};
-class Events : public UIElement {
+class Events : public UIElement, public Mouse {
private:
Graphics::Screen *_screen = nullptr;
Common::Stack<UIElement *> _views;
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 6f851698054..2b092541017 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -98,21 +98,23 @@ bool MM1Engine::setupEnhanced() {
::MM::Xeen::CCArchive *xeenCC = new ::MM::Xeen::CCArchive(
"xeen.cc", "xeen", true);
SearchMan.add("xeen", xeenCC);
- /*
- ::MM::Xeen::CCArchive *darkCC = new ::MM::Xeen::CCArchive(
- "dark.cc", "dark", true);
- SearchMan.add("dark", darkCC);
- */
+
// Load the palette
Common::File f;
if (!f.open("mm4.pal"))
error("Could not load palette");
+ // Load the Xeen palette
byte pal[PALETTE_SIZE];
for (int i = 0; i < PALETTE_SIZE; ++i)
pal[i] = f.readByte() << 2;
g_system->getPaletteManager()->setPalette(pal, 0, PALETTE_COUNT);
+ // Show the mouse cursor
+ g_events->loadCursors();
+ g_events->setCursor(0);
+ g_events->showCursor();
+
return true;
}
diff --git a/engines/mm/mm1/utils/mouse.cpp b/engines/mm/mm1/utils/mouse.cpp
new file mode 100644
index 00000000000..7759b59e3c3
--- /dev/null
+++ b/engines/mm/mm1/utils/mouse.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "graphics/cursorman.h"
+#include "mm/mm1/utils/mouse.h"
+
+namespace MM {
+namespace MM1 {
+
+void Mouse::loadCursors() {
+ _sprites.load("mouse.icn");
+}
+
+void Mouse::setCursor(int cursorId) {
+ Xeen::XSurface cursor;
+ _sprites.draw(cursor, cursorId, Common::Point(0, 0), Xeen::SPRFLAG_RESIZE);
+
+ CursorMan.replaceCursor(cursor.getPixels(), cursor.w, cursor.h, 0, 0, 0);
+ showCursor();
+}
+
+void Mouse::showCursor() {
+ CursorMan.showMouse(true);
+}
+
+void Mouse::hideCursor() {
+ CursorMan.showMouse(false);
+}
+
+bool Mouse::isCursorVisible() const {
+ return CursorMan.isVisible();
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/utils/mouse.h b/engines/mm/mm1/utils/mouse.h
new file mode 100644
index 00000000000..119a9bb6ec4
--- /dev/null
+++ b/engines/mm/mm1/utils/mouse.h
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_UTILS_MOUSE_H
+#define MM1_UTILS_MOUSE_H
+
+#include "mm/xeen/sprites.h"
+
+namespace MM {
+namespace MM1 {
+
+class Mouse {
+private:
+ Xeen::SpriteResource _sprites;
+public:
+ Mouse() {}
+
+ /**
+ * Load the mouse cursors
+ */
+ void loadCursors();
+
+ /**
+ * Set the mouse cursor
+ */
+ void setCursor(int cursorId);
+
+ /**
+ * Shows the mouse cursor
+ */
+ void showCursor();
+
+ /**
+ * Hides the mouse cursor
+ */
+ void hideCursor();
+
+ /**
+ * Returns true if the mouse cursor is visible
+ */
+ bool isCursorVisible() const;
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 6d4c314cdcb..78c8a69cbfb 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -21,6 +21,7 @@ MODULE_OBJS := \
mm1/gfx/dta.o \
mm1/gfx/gfx.o \
mm1/gfx/screen_decoder.o \
+ mm1/utils/mouse.o \
mm1/utils/strings.o \
mm1/views/businesses/business.o \
mm1/views/businesses/market.o \
diff --git a/engines/mm/xeen/files.cpp b/engines/mm/xeen/files.cpp
index 478b7e70bf4..3d3f0235c68 100644
--- a/engines/mm/xeen/files.cpp
+++ b/engines/mm/xeen/files.cpp
@@ -319,7 +319,7 @@ File::File(const Common::String &filename, int ccMode) {
bool File::open(const Common::Path &filename) {
if (!_currentSave || !Common::File::open(filename, *_currentSave)) {
- if (!Common::File::open(filename, *_currentArchive)) {
+ if (!_currentArchive || !Common::File::open(filename, *_currentArchive)) {
// Could not find in current archive, so try intro.cc or in folder
if (!Common::File::open(filename))
error("Could not open file - %s", filename.toString().c_str());
Commit: f10faec4d071a67edfb320fbb0bbf419384de6d2
https://github.com/scummvm/scummvm/commit/f10faec4d071a67edfb320fbb0bbf419384de6d2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Setting actions for the ui buttons
Changed paths:
engines/mm/mm1/messages.cpp
engines/mm/mm1/meta_engine.h
engines/mm/mm1/views_enh/button_container.cpp
engines/mm/mm1/views_enh/button_container.h
engines/mm/mm1/views_enh/game_commands.cpp
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
index 7d29be5f242..52a9112e354 100644
--- a/engines/mm/mm1/messages.cpp
+++ b/engines/mm/mm1/messages.cpp
@@ -25,7 +25,7 @@ namespace MM {
namespace MM1 {
MouseClickMessage::MouseClickMessage(Common::EventType type,
- const Common::Point &pos) : Message() {
+ const Common::Point &pos) : Message(), _pos(pos) {
switch (type) {
case Common::EVENT_RBUTTONUP:
_button = MB_RIGHT;
diff --git a/engines/mm/mm1/meta_engine.h b/engines/mm/mm1/meta_engine.h
index 34a461d1bb0..770bb7f73d4 100644
--- a/engines/mm/mm1/meta_engine.h
+++ b/engines/mm/mm1/meta_engine.h
@@ -36,6 +36,7 @@ enum KeybindingAction {
KEYBIND_TURN_RIGHT,
KEYBIND_STRAFE_LEFT,
KEYBIND_STRAFE_RIGHT,
+ KEYBIND_MAP,
KEYBIND_ORDER,
KEYBIND_PROTECT,
KEYBIND_REST,
@@ -43,6 +44,9 @@ enum KeybindingAction {
KEYBIND_BASH,
KEYBIND_UNLOCK,
KEYBIND_QUICKREF,
+ KEYBIND_VERSION,
+ KEYBIND_MENU,
+ KEYBIND_MINIMAP,
KEYBIND_VIEW_PARTY1,
KEYBIND_VIEW_PARTY2,
KEYBIND_VIEW_PARTY3,
diff --git a/engines/mm/mm1/views_enh/button_container.cpp b/engines/mm/mm1/views_enh/button_container.cpp
index 30357da636c..8d237f17cc2 100644
--- a/engines/mm/mm1/views_enh/button_container.cpp
+++ b/engines/mm/mm1/views_enh/button_container.cpp
@@ -34,8 +34,7 @@ void UIButton::draw(bool pressed) {
}
ButtonContainer::ButtonContainer(const Common::String &name,
- UIElement *owner) : Views::TextView(name, owner),
- _buttonValue(0) {
+ UIElement *owner) : Views::TextView(name, owner) {
}
void ButtonContainer::saveButtons() {
@@ -51,37 +50,34 @@ void ButtonContainer::restoreButtons() {
_buttons = _savedButtons.pop();
}
-void ButtonContainer::addButton(const Common::Rect &bounds, int val,
+void ButtonContainer::addButton(const Common::Rect &bounds, KeybindingAction action,
Xeen::SpriteResource *sprites) {
- _buttons.push_back(UIButton(this, bounds, val, _buttons.size() * 2, sprites, sprites != nullptr));
+ _buttons.push_back(UIButton(this, bounds, action, _buttons.size() * 2, sprites, sprites != nullptr));
}
-void ButtonContainer::addButton(const Common::Rect &bounds, int val,
+void ButtonContainer::addButton(const Common::Rect &bounds, KeybindingAction action,
int frameNum, Xeen::SpriteResource *sprites) {
- _buttons.push_back(UIButton(this, bounds, val, frameNum, sprites, sprites != nullptr));
+ _buttons.push_back(UIButton(this, bounds, action, frameNum, sprites, sprites != nullptr));
}
bool ButtonContainer::msgMouseClick(const MouseClickMessage &msg) {
- _buttonValue = 0;
-
if (msg._button == MouseClickMessage::MB_LEFT) {
const Common::Point pt = msg._pos;
// Check whether any button is selected
for (uint i = 0; i < _buttons.size(); ++i) {
- if (_buttons[i]._bounds.contains(pt) && _buttons[i]._value) {
- _buttonValue = _buttons[i]._value;
-
+ if (_buttons[i]._bounds.contains(pt) && _buttons[i]._action != KEYBIND_NONE) {
// Show the button briefly depressed
_buttons[i].draw(true);
g_engine->getScreen()->update();
- g_system->delayMillis(50);
+ g_system->delayMillis(500);
_buttons[i].draw(false);
g_engine->getScreen()->update();
// Trigger the button action
- // TODO
+ KeybindingAction action = _buttons[i]._action;
+ g_events->msgAction(ActionMessage(action));
return true;
}
diff --git a/engines/mm/mm1/views_enh/button_container.h b/engines/mm/mm1/views_enh/button_container.h
index b2ca3e577b7..59dfc91d6e9 100644
--- a/engines/mm/mm1/views_enh/button_container.h
+++ b/engines/mm/mm1/views_enh/button_container.h
@@ -28,6 +28,7 @@
#include "mm/xeen/sprites.h"
#include "mm/mm1/views/text_view.h"
#include "mm/mm1/events.h"
+#include "mm/mm1/meta_engine.h"
namespace MM {
namespace MM1 {
@@ -39,7 +40,7 @@ class UIButton {
public:
Common::Rect _bounds;
Xeen::SpriteResource *_sprites;
- int _value;
+ KeybindingAction _action;
uint _frameNum, _selectedFrame;
bool _draw;
@@ -47,16 +48,17 @@ public:
* Constructor
*/
UIButton(ButtonContainer *owner, const Common::Rect &bounds,
- int value, uint frameNum, Xeen::SpriteResource *sprites,
+ KeybindingAction action, uint frameNum, Xeen::SpriteResource *sprites,
bool draw) :
- _bounds(bounds), _value(value), _frameNum(frameNum),
+ _bounds(bounds), _action(action), _frameNum(frameNum),
_selectedFrame(frameNum | 1), _sprites(sprites), _draw(draw) {
}
/**
* Constructor
*/
- UIButton() : _value(0), _frameNum(0), _selectedFrame(0), _sprites(nullptr), _draw(false) {
+ UIButton() : _action(KEYBIND_NONE), _frameNum(0), _selectedFrame(0),
+ _sprites(nullptr), _draw(false) {
}
/**
@@ -86,7 +88,6 @@ private:
Common::Stack< Common::Array<UIButton> > _savedButtons;
protected:
Common::Array<UIButton> _buttons;
- int _buttonValue;
bool doScroll(bool fadeIn);
public:
@@ -101,20 +102,11 @@ public:
void restoreButtons();
- void addButton(const Common::Rect &bounds, int val,
+ void addButton(const Common::Rect &bounds, KeybindingAction action,
Xeen::SpriteResource *sprites = nullptr);
- void addButton(const Common::Rect &bounds, int val,
+ void addButton(const Common::Rect &bounds, KeybindingAction action,
int frameNum, Xeen::SpriteResource *sprites = nullptr);
-// void addPartyButtons(XeenEngine *vm);
-
- /**
- * Clears any currently set button value
- */
- void clearEvents() {
- _buttonValue = 0;
- }
-
void draw() override;
bool msgMouseClick(const MouseClickMessage &msg) override;
};
diff --git a/engines/mm/mm1/views_enh/game_commands.cpp b/engines/mm/mm1/views_enh/game_commands.cpp
index efdbabd7435..187dfc49d52 100644
--- a/engines/mm/mm1/views_enh/game_commands.cpp
+++ b/engines/mm/mm1/views_enh/game_commands.cpp
@@ -29,23 +29,26 @@ namespace ViewsEnh {
GameCommands::GameCommands(UIElement *owner) :
ButtonContainer("GameCommands", owner) {
Xeen::SpriteResource *spr = &g_globals->_mainIcons;
- addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_s, spr);
- addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_c, spr);
- addButton(Common::Rect(286, 75, 310, 95), Common::KEYCODE_r, spr);
- addButton(Common::Rect(235, 96, 259, 116), Common::KEYCODE_b, spr);
- addButton(Common::Rect(260, 96, 284, 116), Common::KEYCODE_d, spr);
- addButton(Common::Rect(286, 96, 310, 116), Common::KEYCODE_v, spr);
- addButton(Common::Rect(235, 117, 259, 137), Common::KEYCODE_m, spr);
- addButton(Common::Rect(260, 117, 284, 137), Common::KEYCODE_i, spr);
- addButton(Common::Rect(286, 117, 310, 137), Common::KEYCODE_q, spr);
- addButton(Common::Rect(109, 137, 122, 147), Common::KEYCODE_TAB, spr);
- addButton(Common::Rect(235, 148, 259, 168), Common::KEYCODE_LEFT, spr);
- addButton(Common::Rect(260, 148, 284, 168), Common::KEYCODE_UP, spr);
- addButton(Common::Rect(286, 148, 310, 168), Common::KEYCODE_RIGHT, spr);
- addButton(Common::Rect(235, 169, 259, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT, spr);
- addButton(Common::Rect(260, 169, 284, 189), Common::KEYCODE_DOWN, spr);
- addButton(Common::Rect(286, 169, 310, 189), (Common::KBD_CTRL << 16) | Common::KEYCODE_RIGHT, spr);
- addButton(Common::Rect(236, 11, 308, 69), Common::KEYCODE_EQUALS);
+ addButton(Common::Rect(286, 75, 310, 95), KEYBIND_NONE, spr); // Unlock
+ addButton(Common::Rect(235, 75, 259, 95), KEYBIND_PROTECT, spr); // Protect
+ addButton(Common::Rect(260, 75, 284, 95), KEYBIND_REST, spr); // Rest
+
+ addButton(Common::Rect(235, 96, 259, 116), KEYBIND_BASH, spr); // Bash
+ addButton(Common::Rect(260, 96, 284, 116), KEYBIND_ORDER, spr); // Order
+ addButton(Common::Rect(286, 96, 310, 116), KEYBIND_SEARCH, spr); // Quest items
+
+ addButton(Common::Rect(235, 117, 259, 137), KEYBIND_MAP, spr); // Large map
+ addButton(Common::Rect(260, 117, 284, 137), KEYBIND_VERSION, spr); // Info
+ addButton(Common::Rect(286, 117, 310, 137), KEYBIND_QUICKREF, spr); // quickref
+ addButton(Common::Rect(109, 137, 122, 147), KEYBIND_MENU, spr); // menu
+
+ addButton(Common::Rect(235, 148, 259, 168), KEYBIND_TURN_LEFT, spr);
+ addButton(Common::Rect(260, 148, 284, 168), KEYBIND_FORWARDS, spr);
+ addButton(Common::Rect(286, 148, 310, 168), KEYBIND_TURN_RIGHT, spr);
+ addButton(Common::Rect(235, 169, 259, 189), KEYBIND_STRAFE_LEFT, spr);
+ addButton(Common::Rect(260, 169, 284, 189), KEYBIND_BACKWARDS, spr);
+ addButton(Common::Rect(286, 169, 310, 189), KEYBIND_STRAFE_RIGHT, spr);
+ //addButton(Common::Rect(236, 11, 308, 69), KEYBIND_NONE);
}
} // namespace ViewsEnh
Commit: cc7588bf5a15f46b03d0ef5f8ab435b1ef18774c
https://github.com/scummvm/scummvm/commit/cc7588bf5a15f46b03d0ef5f8ab435b1ef18774c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Fix ui button press/release display
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/messages.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views_enh/button_container.cpp
engines/mm/mm1/views_enh/button_container.h
engines/mm/mm1/views_enh/game.cpp
engines/mm/mm1/views_enh/game.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 328317d83f2..eb12e24ab47 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -88,10 +88,15 @@ void Events::processEvent(Common::Event &ev) {
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
msgAction(ActionMessage((KeybindingAction)ev.customType));
break;
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
+ //case Common::EVENT_MBUTTONDOWN:
+ msgMouseDown(MouseDownMessage(ev.type, ev.mouse));
+ break;
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
//case Common::EVENT_MBUTTONUP:
- msgMouseClick(MouseClickMessage(ev.type, ev.mouse));
+ msgMouseUp(MouseUpMessage(ev.type, ev.mouse));
break;
default:
break;
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index afc89877ddd..ce43d855661 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -134,7 +134,8 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
- MESSAGE(MouseClick);
+ MESSAGE(MouseDown);
+ MESSAGE(MouseUp);
MESSAGE(Action);
MESSAGE(Business);
MESSAGE(Game);
@@ -210,7 +211,8 @@ public:
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
- MESSAGE(MouseClick);
+ MESSAGE(MouseDown);
+ MESSAGE(MouseUp);
#undef MESSAGE
};
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
index 52a9112e354..bdb437427dc 100644
--- a/engines/mm/mm1/messages.cpp
+++ b/engines/mm/mm1/messages.cpp
@@ -24,7 +24,7 @@
namespace MM {
namespace MM1 {
-MouseClickMessage::MouseClickMessage(Common::EventType type,
+MouseMessage::MouseMessage(Common::EventType type,
const Common::Point &pos) : Message(), _pos(pos) {
switch (type) {
case Common::EVENT_RBUTTONUP:
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 3040c52f916..9a1e9f2be4f 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -46,16 +46,18 @@ struct KeypressMessage : public Message, public Common::KeyState {
Message(), Common::KeyState(ks) {}
};
-struct MouseClickMessage : public Message {
+struct MouseMessage : public Message {
enum Button { MB_LEFT, MB_RIGHT, MB_MIDDLE };
Button _button;
Common::Point _pos;
- MouseClickMessage() : Message(), _button(MB_LEFT) {}
- MouseClickMessage(Button btn, const Common::Point &pos) :
+ MouseMessage() : Message(), _button(MB_LEFT) {}
+ MouseMessage(Button btn, const Common::Point &pos) :
Message(), _button(btn), _pos(pos) {}
- MouseClickMessage(Common::EventType type, const Common::Point &pos);
+ MouseMessage(Common::EventType type, const Common::Point &pos);
};
+typedef MouseMessage MouseDownMessage;
+typedef MouseMessage MouseUpMessage;
struct GameMessage : public Message {
Common::String _name;
diff --git a/engines/mm/mm1/views_enh/button_container.cpp b/engines/mm/mm1/views_enh/button_container.cpp
index 8d237f17cc2..ba9e0c6e1a2 100644
--- a/engines/mm/mm1/views_enh/button_container.cpp
+++ b/engines/mm/mm1/views_enh/button_container.cpp
@@ -60,25 +60,38 @@ void ButtonContainer::addButton(const Common::Rect &bounds, KeybindingAction act
_buttons.push_back(UIButton(this, bounds, action, frameNum, sprites, sprites != nullptr));
}
-bool ButtonContainer::msgMouseClick(const MouseClickMessage &msg) {
- if (msg._button == MouseClickMessage::MB_LEFT) {
- const Common::Point pt = msg._pos;
+bool ButtonContainer::msgMouseDown(const MouseDownMessage &msg) {
+ _selectedAction = KEYBIND_NONE;
+ if (msg._button == MouseMessage::MB_LEFT) {
// Check whether any button is selected
for (uint i = 0; i < _buttons.size(); ++i) {
- if (_buttons[i]._bounds.contains(pt) && _buttons[i]._action != KEYBIND_NONE) {
- // Show the button briefly depressed
- _buttons[i].draw(true);
- g_engine->getScreen()->update();
- g_system->delayMillis(500);
+ if (_buttons[i]._bounds.contains(msg._pos) &&
+ _buttons[i]._action != KEYBIND_NONE) {
+ _selectedAction = _buttons[i]._action;
- _buttons[i].draw(false);
- g_engine->getScreen()->update();
+ g_events->redraw();
+ g_events->drawElements();
+ return true;
+ }
+ }
+ }
- // Trigger the button action
- KeybindingAction action = _buttons[i]._action;
- g_events->msgAction(ActionMessage(action));
+ return false;
+}
+
+bool ButtonContainer::msgMouseUp(const MouseUpMessage &msg) {
+ KeybindingAction action = _selectedAction;
+ _selectedAction = KEYBIND_NONE;
+
+ if (msg._button == MouseMessage::MB_LEFT && action != KEYBIND_NONE) {
+ for (uint i = 0; i < _buttons.size(); ++i) {
+ if (_buttons[i]._action == action) {
+ if (_buttons[i]._action == action)
+ g_events->msgAction(ActionMessage(action));
+ g_events->redraw();
+ g_events->drawElements();
return true;
}
}
@@ -93,7 +106,8 @@ void ButtonContainer::draw() {
for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
UIButton &btn = _buttons[btnIndex];
if (btn._draw)
- btn.draw();
+ btn.draw(btn._action != KEYBIND_NONE &&
+ btn._action == _selectedAction);
}
}
diff --git a/engines/mm/mm1/views_enh/button_container.h b/engines/mm/mm1/views_enh/button_container.h
index 59dfc91d6e9..dec50cd0ced 100644
--- a/engines/mm/mm1/views_enh/button_container.h
+++ b/engines/mm/mm1/views_enh/button_container.h
@@ -86,6 +86,7 @@ public:
class ButtonContainer : public Views::TextView {
private:
Common::Stack< Common::Array<UIButton> > _savedButtons;
+ KeybindingAction _selectedAction = KEYBIND_NONE;
protected:
Common::Array<UIButton> _buttons;
@@ -108,7 +109,8 @@ public:
int frameNum, Xeen::SpriteResource *sprites = nullptr);
void draw() override;
- bool msgMouseClick(const MouseClickMessage &msg) override;
+ bool msgMouseDown(const MouseDownMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index e3477eb8b31..3c646d19ec8 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -31,6 +31,13 @@ namespace ViewsEnh {
Game::Game() : TextView("Game"),
_view(this), _commands(this) {
_view.setBounds(Common::Rect(8, 15, 224, 130));
+
+ // Load the Xeen background
+ Common::File f;
+ if (!f.open("back.raw"))
+ error("Could not load background");
+ _bg.create(320, 200);
+ f.read(_bg.getPixels(), 320 * 200);
}
bool Game::msgFocus(const FocusMessage &msg) {
@@ -45,13 +52,8 @@ bool Game::msgUnfocus(const UnfocusMessage &msg) {
void Game::draw() {
if (_needsRedraw) {
- // Load the Xeen background
- Common::File f;
- if (!f.open("back.raw"))
- error("Could not load background");
-
Graphics::ManagedSurface s = getSurface();
- f.read((byte *)s.getPixels(), s.w * s.h);
+ s.blitFrom(_bg);
}
UIElement::draw();
diff --git a/engines/mm/mm1/views_enh/game.h b/engines/mm/mm1/views_enh/game.h
index 54232b2d66c..f02b429f274 100644
--- a/engines/mm/mm1/views_enh/game.h
+++ b/engines/mm/mm1/views_enh/game.h
@@ -22,6 +22,7 @@
#ifndef MM1_VIEWS_ENH_GAME_H
#define MM1_VIEWS_ENH_GAME_H
+#include "graphics/managed_surface.h"
#include "mm/mm1/events.h"
#include "mm/mm1/views/game_view.h"
#include "mm/mm1/views_enh/game_commands.h"
@@ -32,6 +33,7 @@ namespace ViewsEnh {
class Game : public Views::TextView {
private:
+ Graphics::ManagedSurface _bg;
Views::GameView _view;
GameCommands _commands;
public:
Commit: 4ae422f19f4c7c287bbc0c7abd69c2cf19936917
https://github.com/scummvm/scummvm/commit/4ae422f19f4c7c287bbc0c7abd69c2cf19936917
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Beginnings of Training view
Changed paths:
A engines/mm/mm1/views/businesses/training.cpp
A engines/mm/mm1/views/businesses/training.h
A engines/mm/mm1/views_enh/map.cpp
A engines/mm/mm1/views_enh/map.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/meta_engine.cpp
engines/mm/mm1/views/businesses/business.cpp
engines/mm/mm1/views/businesses/market.cpp
engines/mm/mm1/views/businesses/tavern.cpp
engines/mm/mm1/views/businesses/temple.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/mm1/views_enh/button_container.cpp
engines/mm/mm1/views_enh/game_commands.cpp
engines/mm/mm1/views_enh/game_commands.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index e6541f216ef..78514cf3dd0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -152,6 +152,9 @@ dialogs:
d: "D) MAKE DONATION"
thankyou: "THANK YOU!"
protected: "*** TODAY YOU SHALL BE PROTECTED!"
+ training:
+ for_level: "TRAINING FOR LEVEL "
+ no_way: "NO WAY!"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 5ee16df8340..2af9abf85b7 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -69,6 +69,7 @@ struct Character {
uint8 _int = 0, _mgt = 0, _per = 0, _end = 0;
uint8 _spd = 0, _acy = 0, _luc = 0;
uint8 _end2 = 0;
+ uint8 _nextLevel = 0;
uint8 _level = 0;
uint8 _age = 0;
uint32 _exp = 0;
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index eb12e24ab47..2fef2a09336 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -178,6 +178,11 @@ void UIElement::close() {
g_engine->popView();
}
+void UIElement::clearSurface() {
+ Graphics::ManagedSurface s = getSurface();
+ s.fillRect(Common::Rect(s.w, s.h), 0);
+}
+
void UIElement::draw() {
for (size_t i = 0; i < _children.size(); ++i) {
_children[i]->draw();
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index ce43d855661..9473a9f9c1e 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -99,11 +99,23 @@ public:
_bounds = r;
}
+ /**
+ * Gets the element's bounds
+ */
+ Common::Rect getBounds() const {
+ return _bounds;
+ }
+
/**
* Returns a surface for drawing the element
*/
Graphics::ManagedSurface getSurface() const;
+ /**
+ * Clear the surface
+ */
+ virtual void clearSurface();
+
/**
* Draws the element
*/
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 54c5f6b17f2..38a5717f4f4 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -57,6 +57,8 @@ bool Globals::load(bool isEnhanced) {
if (isEnhanced) {
_mainIcons.load("main.icn");
+ _globalSprites.load("global.icn");
+ _tileSprites.load("town.til");
}
return true;
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index f474ff0c475..075cc22897e 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -50,6 +50,8 @@ public:
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
+ Xeen::SpriteResource _globalSprites;
+ Xeen::SpriteResource _tileSprites;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 4f8c3e8c46a..83f321f34ae 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -33,6 +33,7 @@ Map::Map(uint index, const Common::String &name, uint16 id) :
_mapIndex(index), _name(name), _id(id) {
Common::fill((byte *)&_walls[0], (byte *)&_walls[MAP_SIZE], 0);
Common::fill(&_states[0], (byte *)&_states[MAP_SIZE], 0);
+ Common::fill(&_visited[0], &_visited[MAP_SIZE], false);
}
void Map::load() {
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index b61874547a3..94383d2a549 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -65,6 +65,7 @@ private:
public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
+ bool _visited[MAP_SIZE];
public:
Map(uint index, const Common::String &name, uint16 id);
virtual ~Map() {}
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 895bd7e3fa4..f723d2e0706 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -251,6 +251,8 @@ void Maps::loadTown(TownId townId) {
display(0xB1A);
break;
}
+
+ _currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x] = true;
}
void Maps::town15setup() {
@@ -386,8 +388,9 @@ void Maps::turnRight() {
void Maps::step(const Common::Point &delta) {
_mapPos += delta;
- int section = 0, id = 0;
+ _currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x] = true;
+ int section = 0, id = 0;
if (_mapPos.x < 0) {
_mapPos.x = MAP_W - 1;
id = _currentMap->dataWord(16);
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 9a1e9f2be4f..2957c5edc1d 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -90,6 +90,11 @@ struct InfoMessage : public Message {
YNCallback ynCallback = nullptr);
};
+enum LocationType {
+ LOC_TRAINING = 0, LOC_MARKET = 1, LOC_TEMPLE = 2,
+ LOC_BLACKSMITH = 3, LOC_TAVERN = 4
+};
+
struct ValueMessage : public Message {
int _value;
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index 71d69597bec..024785df140 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -49,6 +49,7 @@ static const KeybindingRecord NORMAL_KEYS[] = {
{ KEYBIND_STRAFE_LEFT, "STRAFE_LEFT", "Strafe Left", "C+LEFT", nullptr },
{ KEYBIND_STRAFE_RIGHT, "STRAFE_RIGHT", "Strafe Right", "C+RIGHT", nullptr },
+ { KEYBIND_MINIMAP, "MINIMAP", "Toggle Minimap", "=", nullptr },
{ KEYBIND_ORDER, "ORDER", "Reorder Party", "o", nullptr },
{ KEYBIND_PROTECT, "PROTECT", "Protect", "p", nullptr },
{ KEYBIND_REST, "REST", "Rest", "r", nullptr },
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/businesses/business.cpp
index df75d797747..659c2525190 100644
--- a/engines/mm/mm1/views/businesses/business.cpp
+++ b/engines/mm/mm1/views/businesses/business.cpp
@@ -33,6 +33,7 @@ namespace Businesses {
Business::Business(const Common::String &name) : TextView(name) {
_bounds = getLineBounds(17, 24);
+ _modeString = STRING["dialogs.business.gather"];
}
void Business::draw() {
diff --git a/engines/mm/mm1/views/businesses/market.cpp b/engines/mm/mm1/views/businesses/market.cpp
index b5cdc3da4c9..158414c2a88 100644
--- a/engines/mm/mm1/views/businesses/market.cpp
+++ b/engines/mm/mm1/views/businesses/market.cpp
@@ -40,7 +40,7 @@ Market::Market() : Business("Market") {
}
bool Market::msgFocus(const FocusMessage &msg) {
- g_events->msgBusiness(BusinessMessage(1));
+ g_events->msgBusiness(BusinessMessage(LOC_MARKET));
Maps::Map &map = *g_maps->_currentMap;
_foodCost = FOOD_COST[map[0] - 1];
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/businesses/tavern.cpp
index 38924e3d566..774c19e6949 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/businesses/tavern.cpp
@@ -31,11 +31,10 @@ namespace Views {
namespace Businesses {
Tavern::Tavern() : Business("Tavern") {
- _modeString = STRING["dialogs.business.gather"];
}
bool Tavern::msgFocus(const FocusMessage &msg) {
- g_events->msgBusiness(BusinessMessage(4));
+ g_events->msgBusiness(BusinessMessage(LOC_TAVERN));
g_globals->_currCharacter = &g_globals->_party[0];
return true;
}
diff --git a/engines/mm/mm1/views/businesses/temple.cpp b/engines/mm/mm1/views/businesses/temple.cpp
index 5568681a900..d7ae6bc5140 100644
--- a/engines/mm/mm1/views/businesses/temple.cpp
+++ b/engines/mm/mm1/views/businesses/temple.cpp
@@ -40,11 +40,10 @@ static const byte ALIGNMENT_VALS[3] = { 8, 0x10, 0x18 };
static const byte DONATE_VALS[5] = { 1, 2, 4, 8, 0x10 };
Temple::Temple() : Business("Temple") {
- _modeString = STRING["dialogs.business.gather"];
}
bool Temple::msgFocus(const FocusMessage &msg) {
- g_events->msgBusiness(BusinessMessage(2));
+ g_events->msgBusiness(BusinessMessage(LOC_TEMPLE));
changeCharacter(0);
return true;
diff --git a/engines/mm/mm1/views/businesses/training.cpp b/engines/mm/mm1/views/businesses/training.cpp
new file mode 100644
index 00000000000..b656c0c5fbe
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/training.cpp
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/businesses/training.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+#define MAX_LEVEL 200
+
+Training::Training() : Business("Training") {
+}
+
+bool Training::msgFocus(const FocusMessage &msg) {
+ g_events->msgBusiness(BusinessMessage(LOC_TRAINING));
+ changeCharacter(0);
+
+ return true;
+}
+
+bool Training::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ leave();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ changeCharacter(msg.keycode - Common::KEYCODE_1);
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Training::changeCharacter(uint index) {
+ Maps::Map &map = *g_maps->_currentMap;
+ int i;
+
+ if (index >= g_globals->_party.size())
+ return;
+ Business::changeCharacter(index);
+}
+
+void Training::draw() {
+ Character &c = *g_globals->_currCharacter;
+ Business::draw();
+
+ writeString(18, 1, STRING["dialogs.training.for_level"]);
+ writeNumber(c._nextLevel);
+
+ if (c._nextLevel >= MAX_LEVEL) {
+ writeString(24, 3, STRING["dialogs.training.no_way"]);
+ }
+}
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/training.h b/engines/mm/mm1/views/businesses/training.h
new file mode 100644
index 00000000000..2322f0c25d5
--- /dev/null
+++ b/engines/mm/mm1/views/businesses/training.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_BUSINESSES_TRAINING_H
+#define MM1_VIEWS_BUSINESSES_TRAINING_H
+
+#include "mm/mm1/views/businesses/business.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Businesses {
+
+class Training : public Business {
+protected:
+ /**
+ * Change character
+ */
+ void changeCharacter(uint index) override;
+
+public:
+ Training();
+ virtual ~Training() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void draw() override;
+};
+
+} // namespace Businesses
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index f097983e589..8ab57a60871 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -36,6 +36,7 @@
#include "mm/mm1/views/businesses/market.h"
#include "mm/mm1/views/businesses/tavern.h"
#include "mm/mm1/views/businesses/temple.h"
+#include "mm/mm1/views/businesses/training.h"
namespace MM {
namespace MM1 {
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 3dfa02ed486..b9e56942e6f 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -90,8 +90,7 @@ void TextView::newLine() {
}
void TextView::clearSurface() {
- Graphics::ManagedSurface s = getSurface();
- s.fillRect(Common::Rect(s.w, s.h), 0);
+ UIElement::clearSurface();
_textPos.x = _textPos.y = 0;
}
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 9ec1f92f106..5d1be1660c4 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -62,7 +62,7 @@ protected:
/**
* Clear the surface
*/
- void clearSurface();
+ void clearSurface() override;
/**
* Clear area covered by the given text lines
diff --git a/engines/mm/mm1/views_enh/button_container.cpp b/engines/mm/mm1/views_enh/button_container.cpp
index ba9e0c6e1a2..42a274fd5aa 100644
--- a/engines/mm/mm1/views_enh/button_container.cpp
+++ b/engines/mm/mm1/views_enh/button_container.cpp
@@ -105,7 +105,7 @@ void ButtonContainer::draw() {
for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
UIButton &btn = _buttons[btnIndex];
- if (btn._draw)
+ if (btn._draw && btn._sprites)
btn.draw(btn._action != KEYBIND_NONE &&
btn._action == _selectedAction);
}
diff --git a/engines/mm/mm1/views_enh/game_commands.cpp b/engines/mm/mm1/views_enh/game_commands.cpp
index 187dfc49d52..95f11bf790e 100644
--- a/engines/mm/mm1/views_enh/game_commands.cpp
+++ b/engines/mm/mm1/views_enh/game_commands.cpp
@@ -27,7 +27,8 @@ namespace MM1 {
namespace ViewsEnh {
GameCommands::GameCommands(UIElement *owner) :
- ButtonContainer("GameCommands", owner) {
+ ButtonContainer("GameCommands", owner),
+ _minimap(this) {
Xeen::SpriteResource *spr = &g_globals->_mainIcons;
addButton(Common::Rect(286, 75, 310, 95), KEYBIND_NONE, spr); // Unlock
addButton(Common::Rect(235, 75, 259, 95), KEYBIND_PROTECT, spr); // Protect
@@ -48,7 +49,17 @@ GameCommands::GameCommands(UIElement *owner) :
addButton(Common::Rect(235, 169, 259, 189), KEYBIND_STRAFE_LEFT, spr);
addButton(Common::Rect(260, 169, 284, 189), KEYBIND_BACKWARDS, spr);
addButton(Common::Rect(286, 169, 310, 189), KEYBIND_STRAFE_RIGHT, spr);
- //addButton(Common::Rect(236, 11, 308, 69), KEYBIND_NONE);
+
+ addButton(_minimap.getBounds(), KEYBIND_MINIMAP);
+}
+
+bool GameCommands::msgAction(const ActionMessage & msg) {
+ if (msg._action == KEYBIND_MINIMAP) {
+ _minimap.toggleMinimap();
+ return true;
+ }
+
+ return false;
}
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/game_commands.h b/engines/mm/mm1/views_enh/game_commands.h
index f23b5259f8d..5d247b100a5 100644
--- a/engines/mm/mm1/views_enh/game_commands.h
+++ b/engines/mm/mm1/views_enh/game_commands.h
@@ -23,15 +23,37 @@
#define MM1_VIEWS_ENH_GAME_COMMANDS_H
#include "mm/mm1/views_enh/button_container.h"
+#include "mm/mm1/views_enh/map.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
class GameCommands : public ButtonContainer {
+ class Minimap : public Map {
+ public:
+ bool _minimapOn = false;
+ Minimap(UIElement *owner) : Map(owner) {
+ _bounds = Common::Rect(236, 11, 308, 69);
+ }
+
+ void toggleMinimap() {
+ _minimapOn = !_minimapOn;
+ g_events->redraw();
+ }
+ void draw() override {
+ if (_minimapOn)
+ Map::draw();
+ }
+ };
+
+private:
+ Minimap _minimap;
public:
GameCommands(UIElement *owner);
virtual ~GameCommands() {}
+
+ bool msgAction(const ActionMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/map.cpp b/engines/mm/mm1/views_enh/map.cpp
new file mode 100644
index 00000000000..f7475b32bc1
--- /dev/null
+++ b/engines/mm/mm1/views_enh/map.cpp
@@ -0,0 +1,111 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/map.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+#define BORDER_SIZE 1
+#define TILE_W 10
+#define TILE_H 8
+
+
+Map::Map(UIElement *owner) : UIElement("Map", owner) {
+}
+
+void Map::draw() {
+ MM1::Maps::Maps &maps = g_globals->_maps;
+ MM1::Maps::Map &map = *maps._currentMap;
+ Graphics::ManagedSurface s = getSurface();
+
+ g_globals->_globalSprites.draw(&s, 15,
+ Common::Point(BORDER_SIZE, BORDER_SIZE));
+
+ assert((_bounds.width() - BORDER_SIZE * 2) % TILE_W == 0);
+ assert((_bounds.height() - BORDER_SIZE * 2) % TILE_H == 0);
+ int totalX = (_bounds.width() - BORDER_SIZE * 2) / TILE_W,
+ totalY = (_bounds.height() - BORDER_SIZE * 2) / TILE_H;
+
+ int currentX = maps._mapPos.x;
+ int currentY = maps._mapPos.y;
+ int xStart = CLIP(currentX - (totalX - 1) / 2, 0,
+ MAP_W - totalX);
+ int yStart = CLIP(currentY - (totalY - 1) / 2, 0,
+ MAP_H - totalY);
+
+ // Iterate through the cells
+ for (int yp = BORDER_SIZE, mazeY = yStart + totalY - 1;
+ mazeY >= yStart; yp += TILE_H, --mazeY) {
+ for (int xp = BORDER_SIZE, mazeX = xStart;
+ mazeX < (xStart + totalX); xp += TILE_W, ++mazeX) {
+ bool isVisited = map._visited[mazeY * MAP_W + mazeX];
+
+ if (!isVisited) {
+ g_globals->_tileSprites.draw(&s, 1,
+ Common::Point(xp, yp));
+ } else {
+ Common::Rect r(xp, yp, xp + TILE_W, yp + TILE_H);
+ byte walls = map._walls[mazeY * MAP_W + mazeX];
+ int wallsW = walls & 3;
+ int wallsS = (walls >> 2) & 3;
+ int wallsE = (walls >> 4) & 3;
+ int wallsN = (walls >> 6) & 3;
+
+ // Color visited cells in black, and have a line
+ // on the edges representing walls vs doors
+ s.fillRect(r, 0);
+ if (wallsN != Maps::WALL_NONE)
+ s.hLine(r.left, r.top, r.right - 1,
+ wallsN == Maps::WALL_DOOR ? 128 : 255);
+ if (wallsS != Maps::WALL_NONE)
+ s.hLine(r.left, r.bottom - 1, r.right - 1,
+ wallsS == Maps::WALL_DOOR ? 128 : 255);
+ if (wallsE != Maps::WALL_NONE)
+ s.vLine(r.right - 1, r.top, r.bottom - 1,
+ wallsE == Maps::WALL_DOOR ? 128 : 255);
+ if (wallsW != Maps::WALL_NONE)
+ s.vLine(r.left, r.top, r.bottom - 1,
+ wallsW == Maps::WALL_DOOR ? 128 : 255);
+
+ // Draw arrow if it's the cell the party is on
+ if (mazeX == maps._mapPos.x && mazeY == maps._mapPos.y) {
+ int dir;
+ switch (maps._forwardMask) {
+ case Maps::DIRMASK_N: dir = 1; break;
+ case Maps::DIRMASK_E: dir = 2; break;
+ case Maps::DIRMASK_S: dir = 3; break;
+ default: dir = 4; break;
+ }
+
+ g_globals->_globalSprites.draw(&s,
+ dir, Common::Point(xp, yp));
+ }
+ }
+ }
+ }
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/map.h b/engines/mm/mm1/views_enh/map.h
new file mode 100644
index 00000000000..e17189c43c7
--- /dev/null
+++ b/engines/mm/mm1/views_enh/map.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_MAP_H
+#define MM1_VIEWS_ENH_MAP_H
+
+#include "mm/mm1/events.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class Map : public UIElement {
+public:
+ Map(UIElement *owner);
+ virtual ~Map() {}
+
+ void draw() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 78c8a69cbfb..16a2d90253a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -27,6 +27,7 @@ MODULE_OBJS := \
mm1/views/businesses/market.o \
mm1/views/businesses/tavern.o \
mm1/views/businesses/temple.o \
+ mm1/views/businesses/training.o \
mm1/views/are_you_ready.o \
mm1/views/create_characters.o \
mm1/views/game.o \
@@ -45,6 +46,7 @@ MODULE_OBJS := \
mm1/views_enh/button_container.o \
mm1/views_enh/dialogs.o \
mm1/views_enh/game.o \
+ mm1/views_enh/map.o \
mm1/maps/maps.o \
mm1/maps/map.o \
mm1/maps/map00.o \
Commit: 7fdea42900e7ae5f0e27ffd918cb831a1d29cc52
https://github.com/scummvm/scummvm/commit/7fdea42900e7ae5f0e27ffd918cb831a1d29cc52
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Implemented Statue view
Changed paths:
A engines/mm/mm1/views/locations/location.cpp
A engines/mm/mm1/views/locations/location.h
A engines/mm/mm1/views/locations/market.cpp
A engines/mm/mm1/views/locations/market.h
A engines/mm/mm1/views/locations/statue.cpp
A engines/mm/mm1/views/locations/statue.h
A engines/mm/mm1/views/locations/tavern.cpp
A engines/mm/mm1/views/locations/tavern.h
A engines/mm/mm1/views/locations/temple.cpp
A engines/mm/mm1/views/locations/temple.h
A engines/mm/mm1/views/locations/training.cpp
A engines/mm/mm1/views/locations/training.h
R engines/mm/mm1/views/businesses/business.cpp
R engines/mm/mm1/views/businesses/business.h
R engines/mm/mm1/views/businesses/market.cpp
R engines/mm/mm1/views/businesses/market.h
R engines/mm/mm1/views/businesses/tavern.cpp
R engines/mm/mm1/views/businesses/tavern.h
R engines/mm/mm1/views/businesses/temple.cpp
R engines/mm/mm1/views/businesses/temple.h
R engines/mm/mm1/views/businesses/training.cpp
R engines/mm/mm1/views/businesses/training.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map00.h
engines/mm/mm1/messages.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 78514cf3dd0..5e4deaf517c 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1,5 +1,5 @@
dialogs:
- business:
+ location:
titles:
0: "--TRAINING--"
1: "--MARKET--"
@@ -87,14 +87,25 @@ dialogs:
1: " ARE YOU READY? "
2: "THEN PRESS ENTER!"
statues:
- 1: "SERVICES RENDERED, SECRETS UNFOLD\nTHE BROTHERS TOGETHER\nLEAD TO TREASURES UNTOLD\n\nFIVE TOWNS YOU MUST TRAVEL\nFOR THIS QUEST TO UNRAVEL"
- 2: "SEEK THE WIZARD RANALOU\nIN HIS LAIR AT THE KORIN BLUFFS\nSIX CASTLES HE WILL SEND YOU TO\nBUT DOOM WILL BE QUITE TOUGH!\nCRUELTY AND KINDNESS\nMEASURED THROUGHOUT\nJUDGEMENT DAY IS THEN SOUGHT OUT"
- 3: "ONE BY WATER, ONE BY LAND\nONE BY AIR, AND ONE BY SAND\nTHE WHEEL OF LUCK\nWILL FAVORABLY PAY, THE MORE OF THESE\nMENACING BEASTS YOU SLAY!\nALTHOUGH WISHES MAY COME TRUE\nALL THE BEASTS WILL BECOME ANEW"
- 4: "THERE ARE MANY DUNGEONS LIKE ME\nFIND THE RIGHT PAIR\nAND YOU'LL DISCOVER THE KEY\nTHE ANCIENT SEER OG HAS LOST HIS SIGHT\nTHE IDOLS WILL HELP TO END HIS PLIGHT"
- 5: "IN HONOR OF CORAK...\n\nFOR HIS MAPPING EXPEDITION\nOF THE LAND OF VARN AND REDISCOVERY\nOF THE LOST TOWN OF DUSK"
- 6: "IN HONOR OF GALA...\n\nFOR HER BRAVE ATTEMPT TO WORK WITH THE\nSAVAGES OF THE VOLCANIC ISLES"
- 7: "IN MEMORY OF A TIME LONG AGO...\n\nBEFORE THE DAYS WHEN THE TOWNS\nMOVED UNDERGROUND, DRAGONS WERE\nFEW AND FAR BETWEEN"
- 8: "THIS BEAST ONCE ROAMED THE\nENCHANTED FOREST AND NOW RULES\nA GREAT FORTRESS THERE"
+ stone: "ON THIS STONE STATUE OF "
+ plaque: "A PLAQUE READS..."
+ names:
+ 0: "A HUMAN KNIGHT"
+ 1: "AN ELVEN WIZARD"
+ 2: "A GNOME ROBBER"
+ 3: "A DWARF PALADIN\nPAINTED A BLACK & WHITE CHECKERED MOTIF"
+ 4: "A HUMAN CLERIC"
+ 5: "A BLUE DRAGON"
+ 6: "A GRAY MINOTAUR"
+ messages:
+ 0: "SERVICES RENDERED, SECRETS UNFOLD\nTHE BROTHERS TOGETHER\nLEAD TO TREASURES UNTOLD\n\nFIVE TOWNS YOU MUST TRAVEL\nFOR THIS QUEST TO UNRAVEL"
+ 1: "SEEK THE WIZARD RANALOU\nIN HIS LAIR AT THE KORIN BLUFFS\nSIX CASTLES HE WILL SEND YOU TO\nBUT DOOM WILL BE QUITE TOUGH!\nCRUELTY AND KINDNESS\nMEASURED THROUGHOUT\nJUDGEMENT DAY IS THEN SOUGHT OUT"
+ 2: "ONE BY WATER, ONE BY LAND\nONE BY AIR, AND ONE BY SAND\nTHE WHEEL OF LUCK\nWILL FAVORABLY PAY, THE MORE OF THESE\nMENACING BEASTS YOU SLAY!\nALTHOUGH WISHES MAY COME TRUE\nALL THE BEASTS WILL BECOME ANEW"
+ 3: "THERE ARE MANY DUNGEONS LIKE ME\nFIND THE RIGHT PAIR\nAND YOU'LL DISCOVER THE KEY\nTHE ANCIENT SEER OG HAS LOST HIS SIGHT\nTHE IDOLS WILL HELP TO END HIS PLIGHT"
+ 4: "IN HONOR OF CORAK...\n\nFOR HIS MAPPING EXPEDITION\nOF THE LAND OF VARN AND REDISCOVERY\nOF THE LOST TOWN OF DUSK"
+ 5: "IN HONOR OF GALA...\n\nFOR HER BRAVE ATTEMPT TO WORK WITH THE\nSAVAGES OF THE VOLCANIC ISLES"
+ 6: "IN MEMORY OF A TIME LONG AGO...\n\nBEFORE THE DAYS WHEN THE TOWNS\nMOVED UNDERGROUND, DRAGONS WERE\nFEW AND FAR BETWEEN"
+ 7: "THIS BEAST ONCE ROAMED THE\nENCHANTED FOREST AND NOW RULES\nA GREAT FORTRESS THERE"
tavern:
drink: "A) HAVE A DRINK\r"
tip: "B) TIP BARTENDER\r"
@@ -525,8 +536,8 @@ maps:
training_inside: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
- cd2e: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
- cd53: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
+ stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
+ statue: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
cdf3: "TRAP DOOR!"
cdfe: ", LEVITATION SAVES YOU!"
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 2fef2a09336..d97c157b029 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -32,7 +32,7 @@ namespace MM1 {
Events *g_events;
-Events::Events(bool enhancedMode) : UIElement("", nullptr),
+Events::Events(bool enhancedMode) : UIElement("Root", nullptr),
_enhancedMode(enhancedMode) {
g_events = this;
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 9473a9f9c1e..755c7fdcb2e 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -36,6 +36,8 @@ namespace MM1 {
class Events;
+extern Events *g_events;
+
class UIElement {
friend class Events;
protected:
@@ -141,7 +143,15 @@ public:
if ((*it)->msg##NAME(e)) return true; \
} \
return false; \
- }
+ } \
+ bool send(const Common::String &viewName, const NAME##Message &msg) { \
+ UIElement *view = findView(viewName); \
+ assert(view); \
+ return view->msg##NAME(msg); \
+ } \
+ bool send(const NAME##Message &msg) { \
+ return send("Root", msg); \
+ } \
MESSAGE(Focus);
MESSAGE(Unfocus);
@@ -149,9 +159,9 @@ public:
MESSAGE(MouseDown);
MESSAGE(MouseUp);
MESSAGE(Action);
- MESSAGE(Business);
MESSAGE(Game);
MESSAGE(Info);
+ MESSAGE(Value);
#undef MESSAGE
};
@@ -228,8 +238,6 @@ public:
#undef MESSAGE
};
-extern Events *g_events;
-
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 08a29099928..0f10cdec524 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -100,7 +100,7 @@ bool ViewBase::msgAction(const ActionMessage &msg) {
return true;
}
-bool ViewBase::msgBusiness(const BusinessMessage &msg) {
+bool ViewBase::msgValue(const ValueMessage &msg) {
_businessDisplay = msg._value;
draw();
return true;
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 07a283cad81..18e48ce95b0 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -88,7 +88,7 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
- bool msgBusiness(const BusinessMessage &msg) override;
+ bool msgValue(const ValueMessage &msg) override;
/**
* Updates game state
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 83f321f34ae..d78c5d4f077 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -91,6 +91,14 @@ void Map::checkPartyDead() {
g_events->replaceView("Dead");
}
+uint16 Map::dataWord(uint16 ofs) const {
+ return READ_LE_UINT16(&_data[ofs]);
+}
+
+void Map::dataWord(uint16 ofs, uint16 val) {
+ WRITE_LE_UINT16(&_data[ofs], val);
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 94383d2a549..457c41ff425 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -102,9 +102,8 @@ public:
byte dataByte(uint ofs) const {
return _data[ofs];
}
- uint16 dataWord(uint16 ofs) const {
- return (uint16)_data[ofs] | ((uint16)_data[ofs + 1] << 8);
- }
+ uint16 dataWord(uint16 ofs) const;
+ void dataWord(uint16 ofs, uint16 val);
/**
* Checks whether the party is dead or out of action,
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index a9a94030c7e..b436c9fce44 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -29,6 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define STATUE_VAL 0x412
+
void Map00::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
@@ -122,15 +124,64 @@ void Map00::special06() {
void Map00::special07() { warning("special07"); }
void Map00::special08() { warning("special08"); }
-void Map00::special09() { warning("special09"); }
-void Map00::special10() { warning("special10"); }
-void Map00::special11() { warning("special11"); }
-void Map00::special12() { warning("special12"); }
-void Map00::special13() { warning("special13"); }
-void Map00::special14() { warning("special14"); }
-void Map00::special15() { warning("special15"); }
-void Map00::special16() { warning("special16"); }
-void Map00::special17() { warning("special17"); }
+
+void Map00::special09() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ STRING["maps.map00.stairs"],
+ []() {
+ g_maps->changeMap(0xa11, 1);
+ }
+ ));
+}
+
+void Map00::special10() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 0;
+ searchStatue();
+}
+
+void Map00::special11() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 1;
+ searchStatue();
+}
+
+void Map00::special12() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 2;
+ searchStatue();
+}
+
+void Map00::special13() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 3;
+ searchStatue();
+}
+
+void Map00::special14() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 4;
+ searchStatue();
+}
+
+void Map00::special15() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 5;
+ searchStatue();
+}
+
+void Map00::special16() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 6;
+ searchStatue();
+}
+
+void Map00::special17() {
+ Map &map = *g_maps->_currentMap;
+ map[STATUE_VAL] = 7;
+ searchStatue();
+}
void Map00::special18() {
Sound::sound(SOUND_2);
@@ -174,6 +225,17 @@ void Map00::special23() {
warning("special23");
}
+void Map00::searchStatue() {
+ Sound::sound(SOUND_2);
+ g_events->msgInfo(InfoMessage(
+ STRING["maps.map00.statue"],
+ []() {
+ Map &map = *g_maps->_currentMap;
+ g_events->send("Statue", ValueMessage(map[STATUE_VAL]));
+ }
+ ));
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index 3e3c18f7c7a..6e8f85322a4 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -31,6 +31,8 @@ namespace Maps {
class Map00 : public Map {
typedef void (Map00:: *SpecialFn)();
private:
+ void searchStatue();
+
void special00();
void special01();
void special02();
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 2957c5edc1d..1f6ba91bf5f 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -56,8 +56,20 @@ struct MouseMessage : public Message {
Message(), _button(btn), _pos(pos) {}
MouseMessage(Common::EventType type, const Common::Point &pos);
};
-typedef MouseMessage MouseDownMessage;
-typedef MouseMessage MouseUpMessage;
+struct MouseDownMessage : public MouseMessage {
+ MouseDownMessage() : MouseMessage() {}
+ MouseDownMessage(Button btn, const Common::Point &pos) :
+ MouseMessage(btn, pos) {}
+ MouseDownMessage(Common::EventType type, const Common::Point &pos) :
+ MouseMessage(type, pos) {}
+};
+struct MouseUpMessage : public MouseMessage {
+ MouseUpMessage() : MouseMessage() {}
+ MouseUpMessage(Button btn, const Common::Point &pos) :
+ MouseMessage(btn, pos) {}
+ MouseUpMessage(Common::EventType type, const Common::Point &pos) :
+ MouseMessage(type, pos) {}
+};
struct GameMessage : public Message {
Common::String _name;
@@ -102,7 +114,6 @@ struct ValueMessage : public Message {
ValueMessage(int value) : Message(),
_value(value) {}
};
-typedef ValueMessage BusinessMessage;
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 8ab57a60871..9bbc8376ce8 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -33,10 +33,11 @@
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
-#include "mm/mm1/views/businesses/market.h"
-#include "mm/mm1/views/businesses/tavern.h"
-#include "mm/mm1/views/businesses/temple.h"
-#include "mm/mm1/views/businesses/training.h"
+#include "mm/mm1/views/locations/market.h"
+#include "mm/mm1/views/locations/statue.h"
+#include "mm/mm1/views/locations/tavern.h"
+#include "mm/mm1/views/locations/temple.h"
+#include "mm/mm1/views/locations/training.h"
namespace MM {
namespace MM1 {
@@ -55,9 +56,10 @@ private:
Views::Title _title;
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
- Views::Businesses::Market _market;
- Views::Businesses::Tavern _tavern;
- Views::Businesses::Temple _temple;
+ Views::Locations::Market _market;
+ Views::Locations::Statue _statue;
+ Views::Locations::Tavern _tavern;
+ Views::Locations::Temple _temple;
public:
Dialogs() {}
diff --git a/engines/mm/mm1/views/businesses/business.cpp b/engines/mm/mm1/views/locations/location.cpp
similarity index 80%
rename from engines/mm/mm1/views/businesses/business.cpp
rename to engines/mm/mm1/views/locations/location.cpp
index 659c2525190..99a241a1fb5 100644
--- a/engines/mm/mm1/views/businesses/business.cpp
+++ b/engines/mm/mm1/views/locations/location.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/views/businesses/business.h"
+#include "mm/mm1/views/locations/location.h"
#include "mm/mm1/maps/maps.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
@@ -27,20 +27,20 @@
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
#define DISPLAY_TIMEOUT (5 * FRAME_RATE)
-Business::Business(const Common::String &name) : TextView(name) {
+Location::Location(const Common::String &name) : TextView(name) {
_bounds = getLineBounds(17, 24);
- _modeString = STRING["dialogs.business.gather"];
+ _modeString = STRING["dialogs.location.gather"];
}
-void Business::draw() {
+void Location::draw() {
clearSurface();
writeString(0, 0, g_globals->_currCharacter->_name);
newLine();
- writeString(STRING["dialogs.business.gold"]);
+ writeString(STRING["dialogs.location.gold"]);
writeNumber(g_globals->_currCharacter->_gold);
newLine();
newLine();
@@ -48,19 +48,19 @@ void Business::draw() {
writeString(0, 6, STRING["dialogs.misc.go_back"]);
}
-void Business::displayMessage(int x, const Common::String &msg) {
+void Location::displayMessage(int x, const Common::String &msg) {
clearLines(3, 7);
writeString(x, 5, msg);
_timeoutCtr = DISPLAY_TIMEOUT;
}
-void Business::newLine() {
+void Location::newLine() {
_textPos.x = 0;
if (++_textPos.y >= 24)
_textPos.y = 0;
}
-void Business::gatherGold() {
+void Location::gatherGold() {
uint total = 0;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
total += g_globals->_party[i]._gold;
@@ -70,7 +70,7 @@ void Business::gatherGold() {
g_globals->_currCharacter->_gold = total;
}
-bool Business::subtractGold(uint amount) {
+bool Location::subtractGold(uint amount) {
if (g_globals->_currCharacter->_gold < amount) {
notEnoughGold();
return false;
@@ -80,12 +80,12 @@ bool Business::subtractGold(uint amount) {
}
}
-void Business::notEnoughGold() {
+void Location::notEnoughGold() {
Sound::sound(SOUND_2);
displayMessage(STRING["dialogs.misc.not_enough_gold"]);
}
-void Business::changeCharacter(uint index) {
+void Location::changeCharacter(uint index) {
if (index >= g_globals->_party.size())
return;
@@ -93,7 +93,7 @@ void Business::changeCharacter(uint index) {
redraw();
}
-void Business::leave() {
+void Location::leave() {
SWAP(g_maps->_forwardMask, g_maps->_backwardsMask);
SWAP(g_maps->_leftMask, g_maps->_rightMask);
SWAP(g_maps->_forwardOffset, g_maps->_backwardsOffset);
@@ -103,7 +103,7 @@ void Business::leave() {
g_events->redraw();
}
-bool Business::tick() {
+bool Location::tick() {
if (_timeoutCtr && --_timeoutCtr == 0) {
redraw();
}
@@ -111,7 +111,7 @@ bool Business::tick() {
return TextView::tick();
}
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/business.h b/engines/mm/mm1/views/locations/location.h
similarity index 88%
rename from engines/mm/mm1/views/businesses/business.h
rename to engines/mm/mm1/views/locations/location.h
index 9bac4345c6d..17a3e1b859f 100644
--- a/engines/mm/mm1/views/businesses/business.h
+++ b/engines/mm/mm1/views/locations/location.h
@@ -19,21 +19,20 @@
*
*/
-#ifndef MM1_VIEWS_BUSINESSES_BUSINESS_H
-#define MM1_VIEWS_BUSINESSES_BUSINESS_H
+#ifndef MM1_VIEWS_LOCATIONS_BUSINESS_H
+#define MM1_VIEWS_LOCATIONS_BUSINESS_H
#include "mm/mm1/views/text_view.h"
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
-class Business : public TextView {
-private:
- int _timeoutCtr;
+class Location : public TextView {
protected:
Common::String _modeString;
+ int _timeoutCtr;
protected:
/**
* Clears the bottom part of the window and
@@ -74,8 +73,8 @@ protected:
*/
virtual void changeCharacter(uint index);
public:
- Business(const Common::String &name);
- virtual ~Business() {}
+ Location(const Common::String &name);
+ virtual ~Location() {}
/**
* Draws the initial display for the business
@@ -85,7 +84,7 @@ public:
bool tick() override;
};
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/market.cpp b/engines/mm/mm1/views/locations/market.cpp
similarity index 93%
rename from engines/mm/mm1/views/businesses/market.cpp
rename to engines/mm/mm1/views/locations/market.cpp
index 158414c2a88..dca3a41ae1d 100644
--- a/engines/mm/mm1/views/businesses/market.cpp
+++ b/engines/mm/mm1/views/locations/market.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/views/businesses/market.h"
+#include "mm/mm1/views/locations/market.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
@@ -28,19 +28,19 @@
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
#define TOTAL_FOOD 40
#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
static const byte FOOD_COST[4] = { 5, 10, 20, 200 };
-Market::Market() : Business("Market") {
+Market::Market() : Location("Market") {
_bounds = getLineBounds(21, 24);
}
bool Market::msgFocus(const FocusMessage &msg) {
- g_events->msgBusiness(BusinessMessage(LOC_MARKET));
+ send("GameView", ValueMessage(LOC_MARKET));
Maps::Map &map = *g_maps->_currentMap;
_foodCost = FOOD_COST[map[0] - 1];
@@ -107,7 +107,7 @@ bool Market::buyFood(Character *c) {
return true;
}
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/market.h b/engines/mm/mm1/views/locations/market.h
similarity index 87%
rename from engines/mm/mm1/views/businesses/market.h
rename to engines/mm/mm1/views/locations/market.h
index 2a50081991c..4eb6504e14b 100644
--- a/engines/mm/mm1/views/businesses/market.h
+++ b/engines/mm/mm1/views/locations/market.h
@@ -19,18 +19,18 @@
*
*/
-#ifndef MM1_VIEWS_BUSINESSES_MARKET_H
-#define MM1_VIEWS_BUSINESSES_MARKET_H
+#ifndef MM1_VIEWS_LOCATIONS_MARKET_H
+#define MM1_VIEWS_LOCATIONS_MARKET_H
#include "mm/mm1/data/char.h"
-#include "mm/mm1/views/businesses/business.h"
+#include "mm/mm1/views/locations/location.h"
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
-class Market : public Business {
+class Market : public Location {
private:
int _foodCost = 0;
int _displayCtr = 0;
@@ -54,7 +54,7 @@ public:
bool tick() override;
};
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/locations/statue.cpp b/engines/mm/mm1/views/locations/statue.cpp
new file mode 100644
index 00000000000..2bd5ce1ebba
--- /dev/null
+++ b/engines/mm/mm1/views/locations/statue.cpp
@@ -0,0 +1,88 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/locations/statue.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+#define PAGE1_DELAY (10 * FRAME_RATE)
+
+Statue::Statue() : Location("Statue") {
+}
+
+bool Statue::msgValue(const ValueMessage &msg) {
+ _pageNum = 0;
+ _statueNum = msg._value;
+ addView(this);
+ return true;
+}
+
+bool Statue::msgKeypress(const KeypressMessage &msg) {
+ leave();
+ return true;
+}
+
+void Statue::draw() {
+ switch (_pageNum) {
+ case 0:
+ _bounds = getLineBounds(20, 24);
+ clearSurface();
+
+ writeString(0, 1, STRING["dialogs.statues.stone"]);
+ writeString(STRING[Common::String::format(
+ "dialogs.statues.names.%d", _statueNum)]);
+ newLine();
+ writeString(STRING["dialogs.statues.plaque"]);
+
+ ++_pageNum;
+ _timeoutCtr = PAGE1_DELAY;
+ redraw();
+ break;
+
+ case 1:
+ _bounds = getLineBounds(17, 24);
+ clearSurface();
+
+ writeString(0, 0, STRING[Common::String::format(
+ "dialogs.statues.messages.%d", _statueNum)]);
+
+ Sound::sound(SOUND_2);
+ ++_pageNum;
+ redraw();
+ break;
+
+ default:
+ leave();
+ break;
+ }
+}
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/locations/statue.h b/engines/mm/mm1/views/locations/statue.h
new file mode 100644
index 00000000000..da8424a30aa
--- /dev/null
+++ b/engines/mm/mm1/views/locations/statue.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_LOCATIONS_STATUE_H
+#define MM1_VIEWS_LOCATIONS_STATUE_H
+
+#include "mm/mm1/views/locations/location.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+class Statue : public Location {
+private:
+ int _statueNum = 0;
+ int _pageNum = 0;
+public:
+ Statue();
+ virtual ~Statue() {}
+
+ void draw() override;
+ bool msgValue(const ValueMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/businesses/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
similarity index 94%
rename from engines/mm/mm1/views/businesses/tavern.cpp
rename to engines/mm/mm1/views/locations/tavern.cpp
index 774c19e6949..b5b9d11e728 100644
--- a/engines/mm/mm1/views/businesses/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/views/businesses/tavern.h"
+#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
@@ -28,13 +28,13 @@
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
-Tavern::Tavern() : Business("Tavern") {
+Tavern::Tavern() : Location("Tavern") {
}
bool Tavern::msgFocus(const FocusMessage &msg) {
- g_events->msgBusiness(BusinessMessage(LOC_TAVERN));
+ send("GameView", ValueMessage(LOC_TAVERN));
g_globals->_currCharacter = &g_globals->_party[0];
return true;
}
@@ -73,7 +73,7 @@ bool Tavern::msgKeypress(const KeypressMessage &msg) {
}
void Tavern::draw() {
- Business::draw();
+ Location::draw();
writeString(20, 1, STRING["dialogs.tavern.drink"]);
writeString(20, 2, STRING["dialogs.tavern.tip"]);
@@ -129,7 +129,7 @@ void Tavern::listenForRumors() {
displayMessage(msg);
}
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/tavern.h b/engines/mm/mm1/views/locations/tavern.h
similarity index 86%
rename from engines/mm/mm1/views/businesses/tavern.h
rename to engines/mm/mm1/views/locations/tavern.h
index 003b4697df7..c781b92b48a 100644
--- a/engines/mm/mm1/views/businesses/tavern.h
+++ b/engines/mm/mm1/views/locations/tavern.h
@@ -19,17 +19,17 @@
*
*/
-#ifndef MM1_VIEWS_BUSINESSES_TAVERN_H
-#define MM1_VIEWS_BUSINESSES_TAVERN_H
+#ifndef MM1_VIEWS_LOCATIONS_TAVERN_H
+#define MM1_VIEWS_LOCATIONS_TAVERN_H
-#include "mm/mm1/views/businesses/business.h"
+#include "mm/mm1/views/locations/location.h"
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
-class Tavern : public Business {
+class Tavern : public Location {
private:
/**
* Have a drink
@@ -55,7 +55,7 @@ public:
void draw() override;
};
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
similarity index 95%
rename from engines/mm/mm1/views/businesses/temple.cpp
rename to engines/mm/mm1/views/locations/temple.cpp
index d7ae6bc5140..5b4a78c197d 100644
--- a/engines/mm/mm1/views/businesses/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/views/businesses/temple.h"
+#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
@@ -28,7 +28,7 @@
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
static const uint16 HEAL_COST1[5] = { 2000, 5000, 5000, 2000, 8000 };
static const uint16 HEAL_COST2[5] = { 200, 500, 500, 200, 1000 };
@@ -39,11 +39,11 @@ static const uint16 DONATE_COST[5] = { 100, 100, 100, 25, 200 };
static const byte ALIGNMENT_VALS[3] = { 8, 0x10, 0x18 };
static const byte DONATE_VALS[5] = { 1, 2, 4, 8, 0x10 };
-Temple::Temple() : Business("Temple") {
+Temple::Temple() : Location("Temple") {
}
bool Temple::msgFocus(const FocusMessage &msg) {
- g_events->msgBusiness(BusinessMessage(LOC_TEMPLE));
+ send("GameView", ValueMessage(LOC_TEMPLE));
changeCharacter(0);
return true;
@@ -91,7 +91,7 @@ void Temple::changeCharacter(uint index) {
if (index >= g_globals->_party.size())
return;
- Business::changeCharacter(index);
+ Location::changeCharacter(index);
_isEradicated = false;
@@ -130,7 +130,7 @@ void Temple::changeCharacter(uint index) {
}
void Temple::draw() {
- Business::draw();
+ Location::draw();
writeString(21, 0, STRING["dialogs.temple.service_cost"]);
@@ -226,7 +226,7 @@ void Temple::donate() {
}
}
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/temple.h b/engines/mm/mm1/views/locations/temple.h
similarity index 87%
rename from engines/mm/mm1/views/businesses/temple.h
rename to engines/mm/mm1/views/locations/temple.h
index 3c0671d575f..43e9dcbec36 100644
--- a/engines/mm/mm1/views/businesses/temple.h
+++ b/engines/mm/mm1/views/locations/temple.h
@@ -19,17 +19,17 @@
*
*/
-#ifndef MM1_VIEWS_BUSINESSES_TEMPLE_H
-#define MM1_VIEWS_BUSINESSES_TEMPLE_H
+#ifndef MM1_VIEWS_LOCATIONS_TEMPLE_H
+#define MM1_VIEWS_LOCATIONS_TEMPLE_H
-#include "mm/mm1/views/businesses/business.h"
+#include "mm/mm1/views/locations/location.h"
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
-class Temple : public Business {
+class Temple : public Location {
private:
bool _isEradicated = false;
int _healCost = 0, _uncurseCost = 0;
@@ -55,7 +55,7 @@ public:
void draw() override;
};
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/training.cpp b/engines/mm/mm1/views/locations/training.cpp
similarity index 84%
rename from engines/mm/mm1/views/businesses/training.cpp
rename to engines/mm/mm1/views/locations/training.cpp
index b656c0c5fbe..088a088b3b6 100644
--- a/engines/mm/mm1/views/businesses/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/views/businesses/training.h"
+#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
@@ -28,15 +28,15 @@
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
#define MAX_LEVEL 200
-Training::Training() : Business("Training") {
+Training::Training() : Location("Training") {
}
bool Training::msgFocus(const FocusMessage &msg) {
- g_events->msgBusiness(BusinessMessage(LOC_TRAINING));
+ send("GameView", ValueMessage(LOC_TRAINING));
changeCharacter(0);
return true;
@@ -63,17 +63,12 @@ bool Training::msgKeypress(const KeypressMessage &msg) {
}
void Training::changeCharacter(uint index) {
- Maps::Map &map = *g_maps->_currentMap;
- int i;
-
- if (index >= g_globals->_party.size())
- return;
- Business::changeCharacter(index);
+ Location::changeCharacter(index);
}
void Training::draw() {
Character &c = *g_globals->_currCharacter;
- Business::draw();
+ Location::draw();
writeString(18, 1, STRING["dialogs.training.for_level"]);
writeNumber(c._nextLevel);
@@ -83,7 +78,7 @@ void Training::draw() {
}
}
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/businesses/training.h b/engines/mm/mm1/views/locations/training.h
similarity index 85%
rename from engines/mm/mm1/views/businesses/training.h
rename to engines/mm/mm1/views/locations/training.h
index 2322f0c25d5..f9732aeac71 100644
--- a/engines/mm/mm1/views/businesses/training.h
+++ b/engines/mm/mm1/views/locations/training.h
@@ -19,17 +19,17 @@
*
*/
-#ifndef MM1_VIEWS_BUSINESSES_TRAINING_H
-#define MM1_VIEWS_BUSINESSES_TRAINING_H
+#ifndef MM1_VIEWS_LOCATIONS_TRAINING_H
+#define MM1_VIEWS_LOCATIONS_TRAINING_H
-#include "mm/mm1/views/businesses/business.h"
+#include "mm/mm1/views/locations/location.h"
namespace MM {
namespace MM1 {
namespace Views {
-namespace Businesses {
+namespace Locations {
-class Training : public Business {
+class Training : public Location {
protected:
/**
* Change character
@@ -45,7 +45,7 @@ public:
void draw() override;
};
-} // namespace Businesses
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 16a2d90253a..77bc8a3907c 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -23,11 +23,12 @@ MODULE_OBJS := \
mm1/gfx/screen_decoder.o \
mm1/utils/mouse.o \
mm1/utils/strings.o \
- mm1/views/businesses/business.o \
- mm1/views/businesses/market.o \
- mm1/views/businesses/tavern.o \
- mm1/views/businesses/temple.o \
- mm1/views/businesses/training.o \
+ mm1/views/locations/location.o \
+ mm1/views/locations/market.o \
+ mm1/views/locations/statue.o \
+ mm1/views/locations/tavern.o \
+ mm1/views/locations/temple.o \
+ mm1/views/locations/training.o \
mm1/views/are_you_ready.o \
mm1/views/create_characters.o \
mm1/views/game.o \
@@ -40,6 +41,7 @@ MODULE_OBJS := \
mm1/views/order.o \
mm1/views/protect.o \
mm1/views/quick_ref.o \
+ mm1/views/statue.o \
mm1/views/title.o \
mm1/views/text_view.o \
mm1/views/view_characters.o \
Commit: 366ab226ddd40ea28e2947237a334a479cbb134c
https://github.com/scummvm/scummvm/commit/366ab226ddd40ea28e2947237a334a479cbb134c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Updating message dispatches to use new send method
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/game/search.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views_enh/button_container.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 34ee80855bc..aa04858e54b 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -192,7 +192,7 @@ bool Console::cmdMap(int argc, const char **argv) {
maps.select(maps.getMap(mapId)->getId(), 0);
maps._mapPos.x = x;
maps._mapPos.y = y;
- g_events->msgGame(GameMessage("UPDATE"));
+ g_events->send("Game", GameMessage("UPDATE"));
return false;
}
@@ -206,7 +206,7 @@ bool Console::cmdPos(int argc, const char **argv) {
Maps::Maps &maps = g_globals->_maps;
maps._mapPos.x = strToInt(argv[1]);
maps._mapPos.y = strToInt(argv[2]);
- g_events->msgGame(GameMessage("UPDATE"));
+ g_events->send("Game", GameMessage("UPDATE"));
return false;
}
diff --git a/engines/mm/mm1/game/search.cpp b/engines/mm/mm1/game/search.cpp
index 526372a12f4..77a824e1f7a 100644
--- a/engines/mm/mm1/game/search.cpp
+++ b/engines/mm/mm1/game/search.cpp
@@ -29,7 +29,7 @@ namespace Game {
void Search::execute() {
// TODO: Handle properly
- g_events->msgInfo(InfoMessage("YOU FOUND... NOTHING"));
+ g_events->send(InfoMessage("YOU FOUND... NOTHING"));
}
} // namespace Game
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 457c41ff425..8eb88325706 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -24,6 +24,7 @@
#include "common/array.h"
#include "common/str.h"
+#include "mm/mm1/events.h"
namespace MM {
namespace MM1 {
@@ -110,6 +111,19 @@ public:
* and if so, switches to the death screen
*/
void checkPartyDead();
+
+ /**
+ * Send a message to a UI element
+ */
+ template<class T>
+ bool send(const T &msg) {
+ return g_events->send(msg);
+ }
+ template<class T>
+ bool send(const Common::String &name, const T &msg) {
+ return g_events->send(name, msg);
+ }
+
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index b436c9fce44..01ff5a61768 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -73,7 +73,7 @@ void Map00::special01() {
break;
}
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
2, 0, STRING["maps.map00.sign"],
x, 1, line2
));
@@ -83,7 +83,7 @@ void Map00::special02() { warning("special02"); }
void Map00::special03() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
STRING["maps.map00.market_inside"],
[]() {
g_events->addView("MARKET");
@@ -93,7 +93,7 @@ void Map00::special03() {
void Map00::special04() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
STRING["maps.map00.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(10, 10);
@@ -104,7 +104,7 @@ void Map00::special04() {
void Map00::special05() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
STRING["maps.map00.tavern_inside"],
[]() {
g_events->addView("TAVERN");
@@ -114,7 +114,7 @@ void Map00::special05() {
void Map00::special06() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
STRING["maps.map00.temple_inside"],
[]() {
g_events->addView("TEMPLE");
@@ -127,7 +127,7 @@ void Map00::special08() { warning("special08"); }
void Map00::special09() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
STRING["maps.map00.stairs"],
[]() {
g_maps->changeMap(0xa11, 1);
@@ -185,7 +185,7 @@ void Map00::special17() {
void Map00::special18() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.temple"]
));
@@ -193,7 +193,7 @@ void Map00::special18() {
void Map00::special19() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.jail"]
));
@@ -201,14 +201,14 @@ void Map00::special19() {
void Map00::special20() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.tavern"]
));
}
void Map00::special21() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.training"]
));
@@ -227,7 +227,7 @@ void Map00::special23() {
void Map00::searchStatue() {
Sound::sound(SOUND_2);
- g_events->msgInfo(InfoMessage(
+ send(InfoMessage(
STRING["maps.map00.statue"],
[]() {
Map &map = *g_maps->_currentMap;
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index f723d2e0706..f7f0b9958fc 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -216,7 +216,7 @@ void Maps::select(uint16 id, byte section) {
void Maps::display(uint16 id, byte section) {
select(id, section);
loadTiles();
- g_events->msgGame(GameMessage("DISPLAY"));
+ g_events->send("Game", GameMessage("DISPLAY"));
}
void Maps::loadTown(TownId townId) {
@@ -419,7 +419,7 @@ void Maps::changeMap(uint16 id, byte section) {
select(id, section);
loadTiles();
- g_events->msgGame(GameMessage("UPDATE"));
+ g_events->send("Game", GameMessage("UPDATE"));
}
void Maps::clearSpecial() {
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index a43f789ca38..8c09353be73 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -50,7 +50,7 @@ void Game::draw() {
bool Game::msgAction(const ActionMessage &msg) {
switch (msg._action) {
case KEYBIND_ORDER:
- g_events->msgGame(GameMessage("ORDER"));
+ g_events->send("Game", GameMessage("ORDER"));
return true;
case KEYBIND_SEARCH:
MM1::Game::Search::execute();
diff --git a/engines/mm/mm1/views_enh/button_container.cpp b/engines/mm/mm1/views_enh/button_container.cpp
index 42a274fd5aa..45dbe3a5d4d 100644
--- a/engines/mm/mm1/views_enh/button_container.cpp
+++ b/engines/mm/mm1/views_enh/button_container.cpp
@@ -88,7 +88,7 @@ bool ButtonContainer::msgMouseUp(const MouseUpMessage &msg) {
for (uint i = 0; i < _buttons.size(); ++i) {
if (_buttons[i]._action == action) {
if (_buttons[i]._action == action)
- g_events->msgAction(ActionMessage(action));
+ g_events->send(ActionMessage(action));
g_events->redraw();
g_events->drawElements();
Commit: e7105ee60345ed50a8bee7243e563370c5295277
https://github.com/scummvm/scummvm/commit/e7105ee60345ed50a8bee7243e563370c5295277
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Make message msg methods protected
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/meta_engine.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 755c7fdcb2e..da26af87c13 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -137,6 +137,7 @@ public:
* Handles events
*/
#define MESSAGE(NAME) \
+ protected: \
virtual bool msg##NAME(const NAME##Message &e) { \
for (Common::Array<UIElement *>::iterator it = _children.begin(); \
it != _children.end(); ++it) { \
@@ -144,6 +145,7 @@ public:
} \
return false; \
} \
+ public: \
bool send(const Common::String &viewName, const NAME##Message &msg) { \
UIElement *view = findView(viewName); \
assert(view); \
@@ -175,6 +177,20 @@ protected:
* Process an event
*/
void processEvent(Common::Event &ev);
+
+ /**
+ * Overrides events we want to only go to the focused view
+ */
+ #define MESSAGE(NAME) \
+ bool msg##NAME(const NAME##Message &e) override { \
+ return !_views.empty() ? focusedView()->msg##NAME(e) : false; \
+ }
+ MESSAGE(Focus);
+ MESSAGE(Unfocus);
+ MESSAGE(Keypress);
+ MESSAGE(MouseDown);
+ MESSAGE(MouseUp);
+ #undef MESSAGE
public:
Events(bool enhancedMode);
virtual ~Events();
@@ -222,20 +238,6 @@ public:
bool tick() override {
return !_views.empty() ? focusedView()->tick() : false;
}
-
- /**
- * Overrides events we want to only go to the focused view
- */
- #define MESSAGE(NAME) \
- bool msg##NAME(const NAME##Message &e) override { \
- return !_views.empty() ? focusedView()->msg##NAME(e) : false; \
- }
- MESSAGE(Focus);
- MESSAGE(Unfocus);
- MESSAGE(Keypress);
- MESSAGE(MouseDown);
- MESSAGE(MouseUp);
- #undef MESSAGE
};
} // namespace MM1
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index 024785df140..5d547dbe7ff 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -137,7 +137,7 @@ void MetaEngine::setKeybindingMode(KeybindingMode mode) {
}
void MetaEngine::executeAction(KeybindingAction keyAction) {
- g_engine->msgAction(ActionMessage(keyAction));
+ g_engine->send(ActionMessage(keyAction));
}
} // End of namespace MM1
Commit: 33c5fc3b249e818a51fdb5c7c47065fdfa7b56ae
https://github.com/scummvm/scummvm/commit/33c5fc3b249e818a51fdb5c7c47065fdfa7b56ae
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:54+01:00
Commit Message:
MM: MM1: Added trapdoor
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/messages.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/game_messages.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 5e4deaf517c..a7dc68c1b95 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -538,8 +538,8 @@ maps:
cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
statue: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
- cdf3: "TRAP DOOR!"
- cdfe: ", LEVITATION SAVES YOU!"
+ trapdoor: "TRAP DOOR!"
+ levitate: ", LEVITATION SAVES YOU!"
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
movement:
obstructed:
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 01ff5a61768..ced9467aaac 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -222,7 +222,18 @@ void Map00::special22() {
}
void Map00::special23() {
- warning("special23");
+ Sound::sound(SOUND_2);
+ Common::String msg = STRING["maps.map00.trapdoor"];
+ if (g_globals->_spells._s.levitate)
+ msg += STRING["maps.map00.levitate"];
+
+ send(InfoMessage(msg,
+ [](const Common::KeyState &keyState) {
+ g_events->focusedView()->close();
+ if (!g_globals->_spells._s.levitate)
+ g_maps->changeMap(0xa11, 1);
+ }
+ ));
}
void Map00::searchStatue() {
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
index bdb437427dc..04665b6d83d 100644
--- a/engines/mm/mm1/messages.cpp
+++ b/engines/mm/mm1/messages.cpp
@@ -39,27 +39,55 @@ MouseMessage::MouseMessage(Common::EventType type,
}
}
-InfoMessage::InfoMessage() : Message(), _ynCallback(nullptr) {}
+InfoMessage::InfoMessage() : Message() {}
-InfoMessage::InfoMessage(const Common::String &str,
- YNCallback ynCallback) :
+InfoMessage::InfoMessage(const Common::String &str) : Message() {
+ _lines.push_back(str);
+}
+
+InfoMessage::InfoMessage(int x, int y, const Common::String &str) {
+ _lines.push_back(Line(x, y, str));
+}
+
+InfoMessage::InfoMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2) {
+ _lines.push_back(Line(x1, y1, str1));
+ _lines.push_back(Line(x2, y2, str2));
+}
+
+InfoMessage::InfoMessage(const Common::String &str, YNCallback ynCallback) :
Message(), _ynCallback(ynCallback) {
_lines.push_back(str);
}
-InfoMessage::InfoMessage(int x, int y, const Common::String &str,
- YNCallback ynCallback) :
+InfoMessage::InfoMessage(int x, int y, const Common::String &str, YNCallback ynCallback) :
Message(), _ynCallback(ynCallback) {
_lines.push_back(Line(x, y, str));
}
InfoMessage::InfoMessage(int x1, int y1, const Common::String &str1,
- int x2, int y2, const Common::String &str2,
- YNCallback ynCallback) :
+ int x2, int y2, const Common::String &str2, YNCallback ynCallback) :
Message(), _ynCallback(ynCallback) {
_lines.push_back(Line(x1, y1, str1));
_lines.push_back(Line(x2, y2, str2));
}
+InfoMessage::InfoMessage(const Common::String &str, KeyCallback keyCallback) :
+ Message(), _keyCallback(keyCallback) {
+ _lines.push_back(str);
+}
+
+InfoMessage::InfoMessage(int x, int y, const Common::String &str, KeyCallback keyCallback) :
+ Message(), _keyCallback(keyCallback) {
+ _lines.push_back(Line(x, y, str));
+}
+
+InfoMessage::InfoMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2, KeyCallback keyCallback) :
+ Message(), _keyCallback(keyCallback) {
+ _lines.push_back(Line(x1, y1, str1));
+ _lines.push_back(Line(x2, y2, str2));
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 1f6ba91bf5f..fed4f177b7b 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -79,6 +79,7 @@ struct GameMessage : public Message {
};
typedef void (*YNCallback)();
+typedef void (*KeyCallback)(const Common::KeyState &keyState);
struct InfoMessage : public Message {
struct Line : public Common::Point {
Common::String _text;
@@ -90,16 +91,30 @@ struct InfoMessage : public Message {
Common::Point(x, y), _text(text) {}
};
Common::Array<Line> _lines;
- YNCallback _ynCallback;
+ YNCallback _ynCallback = nullptr;
+ KeyCallback _keyCallback = nullptr;
InfoMessage();
+ InfoMessage(const Common::String &str);
+ InfoMessage(int x, int y, const Common::String &str);
+ InfoMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2);
+
+ InfoMessage(const Common::String &str,
+ YNCallback ynCallback);
+ InfoMessage(int x, int y, const Common::String &str,
+ YNCallback ynCallback);
+ InfoMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2,
+ YNCallback ynCallback);
+
InfoMessage(const Common::String &str,
- YNCallback ynCallback = nullptr);
+ KeyCallback keyCallback);
InfoMessage(int x, int y, const Common::String &str,
- YNCallback ynCallback = nullptr);
+ KeyCallback keyCallback);
InfoMessage(int x1, int y1, const Common::String &str1,
int x2, int y2, const Common::String &str2,
- YNCallback ynCallback = nullptr);
+ KeyCallback keyCallback);
};
enum LocationType {
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 99c2de5eb3e..f22ead4f356 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -51,7 +51,7 @@ void GameMessages::draw() {
}
bool GameMessages::msgInfo(const InfoMessage &msg) {
- if (msg._ynCallback) {
+ if (msg._ynCallback || msg._keyCallback) {
// Do a first draw to show 3d view at new position
g_events->redraw();
g_events->drawElements();
@@ -61,6 +61,7 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
_lines = msg._lines;
_ynCallback = msg._ynCallback;
+ _keyCallback = msg._keyCallback;
redraw();
return true;
@@ -68,7 +69,9 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
bool GameMessages::msgKeypress(const KeypressMessage &msg) {
if (g_events->focusedView() == this) {
- if (msg.keycode == Common::KEYCODE_n) {
+ if (_keyCallback) {
+ _keyCallback(msg);
+ } else if (msg.keycode == Common::KEYCODE_n) {
close();
} else if (msg.keycode == Common::KEYCODE_y) {
close();
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
index 506c1a5c8e5..cbc93db391c 100644
--- a/engines/mm/mm1/views/game_messages.h
+++ b/engines/mm/mm1/views/game_messages.h
@@ -33,6 +33,7 @@ class GameMessages : public TextView {
private:
Common::Array<InfoMessage::Line> _lines;
YNCallback _ynCallback = nullptr;
+ KeyCallback _keyCallback = nullptr;
public:
GameMessages(UIElement *owner);
virtual ~GameMessages() {}
Commit: 4787fae013863cb9ce5c9fc84c584e471f9d3e84
https://github.com/scummvm/scummvm/commit/4787fae013863cb9ce5c9fc84c584e471f9d3e84
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Beginnings of Blacksmith
Changed paths:
A engines/mm/mm1/views/locations/blacksmith.cpp
A engines/mm/mm1/views/locations/blacksmith.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/locations/market.cpp
engines/mm/mm1/views/locations/tavern.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/locations/training.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index d97c157b029..522d34c2249 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -169,6 +169,10 @@ void UIElement::drawElements() {
_children[i]->drawElements();
}
+UIElement *UIElement::findViewGlobally(const Common::String &name) {
+ return g_events->findView(name);
+}
+
void UIElement::focus() {
g_engine->replaceView(this);
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index da26af87c13..90d07497031 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -36,8 +36,6 @@ namespace MM1 {
class Events;
-extern Events *g_events;
-
class UIElement {
friend class Events;
protected:
@@ -56,6 +54,11 @@ private:
*
*/
void drawElements();
+
+ /**
+ * Finds a view globally
+ */
+ static UIElement *findViewGlobally(const Common::String &name);
public:
UIElement(const Common::String &name, UIElement *uiParent);
virtual ~UIElement() {}
@@ -147,7 +150,7 @@ public:
} \
public: \
bool send(const Common::String &viewName, const NAME##Message &msg) { \
- UIElement *view = findView(viewName); \
+ UIElement *view = UIElement::findViewGlobally(viewName); \
assert(view); \
return view->msg##NAME(msg); \
} \
@@ -240,6 +243,8 @@ public:
}
};
+extern Events *g_events;
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index ced9467aaac..cdd8698fda4 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -79,7 +79,15 @@ void Map00::special01() {
));
}
-void Map00::special02() { warning("special02"); }
+void Map00::special02() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map00.blacksmith_inside"],
+ []() {
+ g_events->addView("Blacksmith");
+ }
+ ));
+}
void Map00::special03() {
Sound::sound(SOUND_2);
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 9bbc8376ce8..2b74b2278df 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -33,6 +33,7 @@
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/market.h"
#include "mm/mm1/views/locations/statue.h"
#include "mm/mm1/views/locations/tavern.h"
@@ -56,6 +57,7 @@ private:
Views::Title _title;
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
+ Views::Locations::Blacksmith _blacksmith;
Views::Locations::Market _market;
Views::Locations::Statue _statue;
Views::Locations::Tavern _tavern;
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 0a7978b7b48..1398868eb56 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -203,7 +203,7 @@ void GameView::drawDialogMessage() {
void GameView::drawBusinessName() {
writeString(10, 15, STRING[Common::String::format(
- "dialogs.business.titles.%d", _businessDisplay)]);
+ "dialogs.location.titles.%d", _businessDisplay)]);
_businessDisplay = -1;
}
diff --git a/engines/mm/mm1/views/locations/blacksmith.cpp b/engines/mm/mm1/views/locations/blacksmith.cpp
new file mode 100644
index 00000000000..f7f14f22ff3
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith.cpp
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/locations/blacksmith.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+Blacksmith::Blacksmith() : Location("Blacksmith") {
+}
+
+bool Blacksmith::msgFocus(const FocusMessage &msg) {
+ send("View", ValueMessage(LOC_BLACKSMITH));
+ changeCharacter(0);
+
+ return true;
+}
+
+bool Blacksmith::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ leave();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ changeCharacter(msg.keycode - Common::KEYCODE_1);
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Blacksmith::draw() {
+ clearSurface();
+}
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/locations/blacksmith.h b/engines/mm/mm1/views/locations/blacksmith.h
new file mode 100644
index 00000000000..5ff26bc3cd2
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_H
+#define MM1_VIEWS_LOCATIONS_BLACKSMITH_H
+
+#include "mm/mm1/views/locations/location.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+class Blacksmith : public Location {
+public:
+ Blacksmith();
+ virtual ~Blacksmith() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void draw() override;
+};
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/locations/market.cpp b/engines/mm/mm1/views/locations/market.cpp
index dca3a41ae1d..4fe84e76c74 100644
--- a/engines/mm/mm1/views/locations/market.cpp
+++ b/engines/mm/mm1/views/locations/market.cpp
@@ -40,7 +40,7 @@ Market::Market() : Location("Market") {
}
bool Market::msgFocus(const FocusMessage &msg) {
- send("GameView", ValueMessage(LOC_MARKET));
+ send("View", ValueMessage(LOC_MARKET));
Maps::Map &map = *g_maps->_currentMap;
_foodCost = FOOD_COST[map[0] - 1];
diff --git a/engines/mm/mm1/views/locations/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
index b5b9d11e728..c8d4b065bcb 100644
--- a/engines/mm/mm1/views/locations/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -34,7 +34,7 @@ Tavern::Tavern() : Location("Tavern") {
}
bool Tavern::msgFocus(const FocusMessage &msg) {
- send("GameView", ValueMessage(LOC_TAVERN));
+ send("View", ValueMessage(LOC_TAVERN));
g_globals->_currCharacter = &g_globals->_party[0];
return true;
}
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 5b4a78c197d..8449a8e43b5 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -43,7 +43,7 @@ Temple::Temple() : Location("Temple") {
}
bool Temple::msgFocus(const FocusMessage &msg) {
- send("GameView", ValueMessage(LOC_TEMPLE));
+ send("View", ValueMessage(LOC_TEMPLE));
changeCharacter(0);
return true;
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index 088a088b3b6..64a55b48ae7 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -36,7 +36,7 @@ Training::Training() : Location("Training") {
}
bool Training::msgFocus(const FocusMessage &msg) {
- send("GameView", ValueMessage(LOC_TRAINING));
+ send("View", ValueMessage(LOC_TRAINING));
changeCharacter(0);
return true;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 77bc8a3907c..fe128f3e45c 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -24,6 +24,7 @@ MODULE_OBJS := \
mm1/utils/mouse.o \
mm1/utils/strings.o \
mm1/views/locations/location.o \
+ mm1/views/locations/blacksmith.o \
mm1/views/locations/market.o \
mm1/views/locations/statue.o \
mm1/views/locations/tavern.o \
Commit: c33874faa6f930cf2f2facc095a22178dd98beee
https://github.com/scummvm/scummvm/commit/c33874faa6f930cf2f2facc095a22178dd98beee
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Implement leprechaun
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/messages.h
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/locations/location.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index a7dc68c1b95..02b2da91d53 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -535,7 +535,7 @@ maps:
temple_inside: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
training_inside: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
- cc53: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
+ leprechaun: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
statue: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
trapdoor: "TRAP DOOR!"
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index cdd8698fda4..63955580693 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -29,6 +29,11 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define TOWN_NUM 0x2fe
+#define LEPRECHAUN_MAP_ID1 0x2ff
+#define LEPRECHAUN_MAP_ID2 0x304
+#define LEPRECHAUN_MAP_X 0x309
+#define LEPRECHAUN_MAP_Y 0x30E
#define STATUE_VAL 0x412
void Map00::special() {
@@ -52,7 +57,9 @@ void Map00::special() {
g_events->addView("Encounter");
}
-void Map00::special00() { warning("special00"); }
+void Map00::special00() {
+
+}
void Map00::special01() {
Sound::sound(SOUND_2);
@@ -130,8 +137,58 @@ void Map00::special06() {
));
}
-void Map00::special07() { warning("special07"); }
-void Map00::special08() { warning("special08"); }
+void Map00::special07() {
+ warning("special07");
+}
+
+void Map00::special08() {
+ Sound::sound(SOUND_2);
+ InfoMessage msg(
+ STRING["maps.map00.leprechaun"],
+ [](const Common::KeyState &keyState) {
+ Maps &maps = *g_maps;
+ Map &map = *g_maps->_currentMap;
+
+ switch (keyState.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ maps.turnAround();
+ g_events->focusedView()->close();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ map[TOWN_NUM] = keyState.ascii;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c._gems) {
+ c._gems--;
+
+ int townIndex = map[TOWN_NUM] - Common::KEYCODE_1;
+ maps._mapPos.x = map[LEPRECHAUN_MAP_X + townIndex];
+ maps._mapPos.y = map[LEPRECHAUN_MAP_Y + townIndex];
+ maps.changeMap(
+ map[LEPRECHAUN_MAP_ID1 + townIndex] |
+ (map[LEPRECHAUN_MAP_ID2 + townIndex] << 8),
+ 1);
+
+ g_events->redraw();
+ return;
+ }
+ }
+
+ maps._mapPos = Common::Point(8, 5);
+ g_events->send("View", GameMessage("UPDATE"));
+ break;
+ }
+ }
+ );
+
+ msg._largeMessage = true;
+ send(msg);
+}
void Map00::special09() {
Sound::sound(SOUND_2);
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index f7f0b9958fc..12a16efc456 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -295,9 +295,8 @@ uint Maps::getIndex(uint16 id, byte section) {
uint idx = LOOKUPS_START[section];
// Find map by Id
- for (; id != _maps[idx]->getId(); ++idx) {
- assert(idx < _maps.size());
- }
+ for (; idx < _maps.size() && id != _maps[idx]->getId(); ++idx) {}
+ assert(idx < _maps.size());
_colorOffset = COLOR_OFFSET[idx];
return idx;
@@ -386,6 +385,13 @@ void Maps::turnRight() {
_backwardsOffset = tempOffset;
}
+void Maps::turnAround() {
+ SWAP(g_maps->_forwardMask, g_maps->_backwardsMask);
+ SWAP(g_maps->_leftMask, g_maps->_rightMask);
+ SWAP(g_maps->_forwardOffset, g_maps->_backwardsOffset);
+ SWAP(g_maps->_leftOffset, g_maps->_rightOffset);
+}
+
void Maps::step(const Common::Point &delta) {
_mapPos += delta;
_currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x] = true;
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 1e60a91602e..2e8ac565af6 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -135,6 +135,11 @@ public:
*/
void turnRight();
+ /**
+ * Turn around
+ */
+ void turnAround();
+
/**
* Move a step
*/
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index fed4f177b7b..6366573dcff 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -93,6 +93,7 @@ struct InfoMessage : public Message {
Common::Array<Line> _lines;
YNCallback _ynCallback = nullptr;
KeyCallback _keyCallback = nullptr;
+ bool _largeMessage = false;
InfoMessage();
InfoMessage(const Common::String &str);
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index f22ead4f356..0e9652c95b2 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -63,6 +63,11 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
_ynCallback = msg._ynCallback;
_keyCallback = msg._keyCallback;
+ if (msg._largeMessage)
+ _bounds = getLineBounds(17, 24);
+ else
+ _bounds = getLineBounds(21, 24);
+
redraw();
return true;
}
diff --git a/engines/mm/mm1/views/locations/location.cpp b/engines/mm/mm1/views/locations/location.cpp
index 99a241a1fb5..73cc693a767 100644
--- a/engines/mm/mm1/views/locations/location.cpp
+++ b/engines/mm/mm1/views/locations/location.cpp
@@ -94,11 +94,7 @@ void Location::changeCharacter(uint index) {
}
void Location::leave() {
- SWAP(g_maps->_forwardMask, g_maps->_backwardsMask);
- SWAP(g_maps->_leftMask, g_maps->_rightMask);
- SWAP(g_maps->_forwardOffset, g_maps->_backwardsOffset);
- SWAP(g_maps->_leftOffset, g_maps->_rightOffset);
-
+ g_maps->turnAround();
close();
g_events->redraw();
}
Commit: cce5becae4a373befc4117c095cce763a85a7823
https://github.com/scummvm/scummvm/commit/cce5becae4a373befc4117c095cce763a85a7823
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Rename character max spell level
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/view_characters.cpp
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 289d27d0db5..b1ebd668369 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -55,7 +55,7 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsUint16LE(_sp);
s.syncAsUint16LE(_spMax);
s.syncAsByte(_sp2);
- s.syncAsByte(_sp1);
+ s.syncAsByte(_maxSpellLevel);
s.syncAsUint16LE(_gems);
s.syncAsUint16LE(_hp);
s.syncAsUint16LE(_hp2);
@@ -86,7 +86,7 @@ void Character::clear() {
_age = 0;
_exp = 0;
_sp = _spMax = 0;
- _sp1 = _sp2 = 0;
+ _maxSpellLevel = _sp2 = 0;
_gems = 0;
_hp = _hp2 = _hpMax = 0;
_gold = 0;
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 2af9abf85b7..d257eca6f3c 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -74,7 +74,7 @@ struct Character {
uint8 _age = 0;
uint32 _exp = 0;
uint16 _sp = 0, _spMax = 0;
- uint8 _sp1 = 0, _sp2 = 0;
+ uint8 _maxSpellLevel = 0, _sp2 = 0;
uint16 _gems = 0;
uint16 _hp = 0, _hp2 = 0, _hpMax = 0;
uint32 _gold = 0;
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index aac1ebb3ea1..48d9444c203 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -173,7 +173,7 @@ void CreateCharacters::NewCharacter::setSP(int amount) {
level = 1;
re._sp = re._spMax = level + 3;
- re._sp1 = re._sp2 = 1;
+ re._maxSpellLevel = re._sp2 = 1;
}
/*------------------------------------------------------------------------*/
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/view_characters.cpp
index 11502fb8267..79f033621d6 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/view_characters.cpp
@@ -120,7 +120,7 @@ void CharacterStats::printStats() {
writeNumber(re._spMax);
_textPos.x = 22;
writeChar('(');
- writeNumber(re._sp1);
+ writeNumber(re._maxSpellLevel);
writeChar(')');
_textPos.x = 26;
writeString(STRING["stats.attributes.gems"]);
Commit: 0e9226480e380385f96354864f57bdcc2246cf8f
https://github.com/scummvm/scummvm/commit/0e9226480e380385f96354864f57bdcc2246cf8f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Clarifying more character fields
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/locations/temple.cpp
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index b1ebd668369..f197662a092 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -32,25 +32,26 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_alignment);
s.syncAsByte(_race);
s.syncAsByte(_class);
- s.skip(1);
+
+ s.syncAsByte(_intBase);
s.syncAsByte(_int);
- s.skip(1);
+ s.syncAsByte(_mgtBase);
s.syncAsByte(_mgt);
- s.skip(1);
+ s.syncAsByte(_perBase);
s.syncAsByte(_per);
- s.skip(1);
+ s.syncAsByte(_endBase);
s.syncAsByte(_end);
- s.skip(1);
+ s.syncAsByte(_spdBase);
s.syncAsByte(_spd);
- s.skip(1);
+ s.syncAsByte(_acyBase);
s.syncAsByte(_acy);
- s.skip(1);
+ s.syncAsByte(_lucBase);
s.syncAsByte(_luc);
- s.skip(1);
+ s.syncAsByte(_nextLevel);
s.syncAsByte(_level);
s.syncAsByte(_age);
- s.skip(1);
+ s.syncAsByte(_field26);
s.syncAsUint32LE(_exp);
s.syncAsUint16LE(_sp);
s.syncAsUint16LE(_spMax);
@@ -96,7 +97,8 @@ void Character::clear() {
Common::fill(_equipped, _equipped + INVENTORY_COUNT, 0);
Common::fill(_backpack, _backpack + INVENTORY_COUNT, 0);
- _field11 = 0;
+ _alignmentInitial = GOOD;
+ _alignment = GOOD;
_v58 = _v59 = _v62 = _v63 = _v64 = _v65 = 0;
_v66 = _v67 = _v6c = _v6f = 0;
}
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index d257eca6f3c..e39cd27d6af 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -61,20 +61,24 @@ enum Town {
struct Character {
char _name[16] = { 0 };
Sex _sex = MALE;
- int _field11 = 0;
Alignment _alignmentInitial = GOOD;
Alignment _alignment = GOOD;
Race _race = HUMAN;
CharacterClass _class = NONE;
+
uint8 _int = 0, _mgt = 0, _per = 0, _end = 0;
uint8 _spd = 0, _acy = 0, _luc = 0;
- uint8 _end2 = 0;
+ uint8 _intBase = 0, _mgtBase = 0, _perBase = 0;
+ uint8 _endBase = 0, _spdBase = 0, _acyBase = 0;
+ uint8 _lucBase = 0;
+
uint8 _nextLevel = 0;
uint8 _level = 0;
uint8 _age = 0;
+ uint8 _field26 = 0;
uint32 _exp = 0;
uint16 _sp = 0, _spMax = 0;
- uint8 _maxSpellLevel = 0, _sp2 = 0;
+ uint8 _sp2 = 0, _maxSpellLevel = 0;
uint16 _gems = 0;
uint16 _hp = 0, _hp2 = 0, _hpMax = 0;
uint32 _gold = 0;
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 63955580693..71c500b268f 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -101,7 +101,7 @@ void Map00::special03() {
send(InfoMessage(
STRING["maps.map00.market_inside"],
[]() {
- g_events->addView("MARKET");
+ g_events->addView("Market");
}
));
}
@@ -122,7 +122,7 @@ void Map00::special05() {
send(InfoMessage(
STRING["maps.map00.tavern_inside"],
[]() {
- g_events->addView("TAVERN");
+ g_events->addView("Tavern");
}
));
}
@@ -132,13 +132,19 @@ void Map00::special06() {
send(InfoMessage(
STRING["maps.map00.temple_inside"],
[]() {
- g_events->addView("TEMPLE");
+ g_events->addView("Temple");
}
));
}
void Map00::special07() {
- warning("special07");
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map00.training_inside"],
+ []() {
+ g_events->addView("Training");
+ }
+ ));
}
void Map00::special08() {
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 48d9444c203..7b19f957404 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -123,7 +123,8 @@ void CreateCharacters::NewCharacter::save() {
re._food = 10;
re._backpack[0] = 1;
- re._v6f = re._field11 ? 0x10 : 0;
+ const int ALIGNMENT_VALS[3] = { 0, 0x10, 0x20 };
+ re._v6f = ALIGNMENT_VALS[re._alignmentInitial];
g_globals->_roster.save();
}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 2b74b2278df..3e21de0b11d 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -62,6 +62,7 @@ private:
Views::Locations::Statue _statue;
Views::Locations::Tavern _tavern;
Views::Locations::Temple _temple;
+ Views::Locations::Training _training;
public:
Dialogs() {}
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 8449a8e43b5..024eba23dcf 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -168,8 +168,8 @@ void Temple::restoreHealth() {
if (_isEradicated) {
c._age += 10;
- if (c._end2)
- c._end = --c._end2;
+ if (c._endBase)
+ c._end = --c._endBase;
}
redraw();
@@ -182,7 +182,7 @@ void Temple::uncurseItems() {
for (int i = 0; i < INVENTORY_COUNT; ++i) {
if (c._equipped[i]) {
getItem(c._equipped[i]);
- if (c._field11 == 0xff)
+ if (g_globals->_currItem._field10 == 0xff)
c._equipped[i] = 0;
}
}
Commit: aee5adc014c5d98170f268f60e4c65f8fb14512a
https://github.com/scummvm/scummvm/commit/aee5adc014c5d98170f268f60e4c65f8fb14512a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Training calculations, display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/locations/training.cpp
engines/mm/mm1/views/locations/training.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 02b2da91d53..bb1dafd2324 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -166,6 +166,10 @@ dialogs:
training:
for_level: "TRAINING FOR LEVEL "
no_way: "NO WAY!"
+ need: "NEED %d MORE"
+ cost: "COST %d GOLD"
+ xp: "EXPERIENCE POINTS"
+ commence: "A) COMMENCE TRAINING"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index f197662a092..d77b1835dcd 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -48,7 +48,7 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_lucBase);
s.syncAsByte(_luc);
- s.syncAsByte(_nextLevel);
+ s.syncAsByte(_levelBase);
s.syncAsByte(_level);
s.syncAsByte(_age);
s.syncAsByte(_field26);
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index e39cd27d6af..63974e47e60 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -72,7 +72,7 @@ struct Character {
uint8 _endBase = 0, _spdBase = 0, _acyBase = 0;
uint8 _lucBase = 0;
- uint8 _nextLevel = 0;
+ uint8 _levelBase = 0;
uint8 _level = 0;
uint8 _age = 0;
uint8 _field26 = 0;
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index 64a55b48ae7..757767155c1 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -32,6 +32,13 @@ namespace Locations {
#define MAX_LEVEL 200
+const int TRAINING_COSTS1[7] = {
+ 25, 50, 100, 200, 400, 800, 1500
+};
+const int TRAINING_COSTS2[7] = {
+ 40, 75, 150, 300, 600, 1200, 2500
+};
+
Training::Training() : Location("Training") {
}
@@ -64,17 +71,69 @@ bool Training::msgKeypress(const KeypressMessage &msg) {
void Training::changeCharacter(uint index) {
Location::changeCharacter(index);
+ Character &c = *g_globals->_currCharacter;
+
+ _currLevel = c._levelBase;
+ if (_currLevel >= MAX_LEVEL)
+ return;
+
+ // Initialize fields
+ _expTotal = 0;
+ _remainingExp = 0;
+ _expAmount = 0;
+ _cost = _cost2 = 0;
+ _canTrain = false;
+ _canAfford = false;
+ _class = c._class;
+
+ if (_class == KNIGHT || _class == CLERIC || _class == ROBBER) {
+ _expTotal = 1500;
+ _expAmount = 150000;
+
+ if (_currLevel != 0) {
+ _cost = _currLevel >= 8 ? 3000 :
+ TRAINING_COSTS1[_currLevel - 1];
+ }
+ } else {
+ _expTotal = 2000;
+ _expAmount = 200000;
+ _cost = _currLevel >= 8 ? 4000 :
+ TRAINING_COSTS2[_currLevel - 1];
+ }
+
+ for (int level = _currLevel - 1, ctr = 0; level > 0; --level) {
+ _expTotal *= 16;
+
+ if (++ctr >= 7) {
+ while (--level > 0)
+ _expTotal += _expAmount;
+ break;
+ }
+ }
+
+ _remainingExp = _expTotal - c._exp;
+ _canTrain = _remainingExp > 0;
+ _canAfford = (int)c._gold >= _cost;
}
void Training::draw() {
- Character &c = *g_globals->_currCharacter;
Location::draw();
writeString(18, 1, STRING["dialogs.training.for_level"]);
- writeNumber(c._nextLevel);
+ writeNumber(_currLevel + 1);
- if (c._nextLevel >= MAX_LEVEL) {
+ if (_currLevel >= MAX_LEVEL) {
writeString(24, 3, STRING["dialogs.training.no_way"]);
+
+ } else if (_remainingExp > 0) {
+ writeString(21, 3, Common::String::format(
+ STRING["dialogs.training.need"].c_str(), _remainingExp));
+ writeString(20, 5, STRING["dialogs.training.xp"]);
+
+ } else {
+ writeString(21, 3, Common::String::format(
+ STRING["dialogs.training.cost"].c_str(), _cost));
+ writeString(18, 5, STRING["dialogs.training.cost"]);
}
}
diff --git a/engines/mm/mm1/views/locations/training.h b/engines/mm/mm1/views/locations/training.h
index f9732aeac71..404b9cdbbe2 100644
--- a/engines/mm/mm1/views/locations/training.h
+++ b/engines/mm/mm1/views/locations/training.h
@@ -22,6 +22,7 @@
#ifndef MM1_VIEWS_LOCATIONS_TRAINING_H
#define MM1_VIEWS_LOCATIONS_TRAINING_H
+#include "mm/mm1/data/char.h"
#include "mm/mm1/views/locations/location.h"
namespace MM {
@@ -30,6 +31,15 @@ namespace Views {
namespace Locations {
class Training : public Location {
+private:
+ int _currLevel = 0;
+ CharacterClass _class = KNIGHT;
+ int _expTotal = 0;
+ int _remainingExp = 0;
+ int _expAmount = 0;
+ int _cost = 0, _cost2;
+ bool _canTrain = false;
+ bool _canAfford = false;
protected:
/**
* Change character
Commit: 7ed05692f3778f60cc28f19601ee9013f2ef69e2
https://github.com/scummvm/scummvm/commit/7ed05692f3778f60cc28f19601ee9013f2ef69e2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Implementing some of the training logic for increasing level
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/locations/training.cpp
engines/mm/mm1/views/locations/training.h
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index d77b1835dcd..3dc53822b33 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -50,16 +50,16 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_levelBase);
s.syncAsByte(_level);
+ s.syncAsByte(_ageBase);
s.syncAsByte(_age);
- s.syncAsByte(_field26);
s.syncAsUint32LE(_exp);
s.syncAsUint16LE(_sp);
s.syncAsUint16LE(_spMax);
s.syncAsByte(_sp2);
s.syncAsByte(_maxSpellLevel);
s.syncAsUint16LE(_gems);
+ s.syncAsUint16LE(_hpBase);
s.syncAsUint16LE(_hp);
- s.syncAsUint16LE(_hp2);
s.syncAsUint16LE(_hpMax);
s.syncAsUint16LE(_gold);
s.skip(2);
@@ -89,7 +89,7 @@ void Character::clear() {
_sp = _spMax = 0;
_maxSpellLevel = _sp2 = 0;
_gems = 0;
- _hp = _hp2 = _hpMax = 0;
+ _hpBase = _hp = _hpMax = 0;
_gold = 0;
_ac = 0;
_food = 0;
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 63974e47e60..9266283b179 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -74,13 +74,13 @@ struct Character {
uint8 _levelBase = 0;
uint8 _level = 0;
+ uint8 _ageBase = 0;
uint8 _age = 0;
- uint8 _field26 = 0;
uint32 _exp = 0;
uint16 _sp = 0, _spMax = 0;
uint8 _sp2 = 0, _maxSpellLevel = 0;
uint16 _gems = 0;
- uint16 _hp = 0, _hp2 = 0, _hpMax = 0;
+ uint16 _hpBase = 0, _hp = 0, _hpMax = 0;
uint32 _gold = 0;
byte _ac = 0;
uint8 _food = 0;
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 7b19f957404..85949534b07 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -145,7 +145,7 @@ void CreateCharacters::NewCharacter::setHP(int hp) {
else if (_attribs1[ENDURANCE] < 8)
hp -= 1;
- re._hp = re._hp2 = re._hpMax = hp;
+ re._hpBase = re._hp = re._hpMax = hp;
int ac = 0;
if (_attribs1[SPEED] >= 19)
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 024eba23dcf..8b2e645905f 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -164,7 +164,7 @@ void Temple::restoreHealth() {
if (subtractGold(_healCost)) {
Character &c = *g_globals->_currCharacter;
c._condition = FINE;
- c._hp = c._hp2;
+ c._hpBase = c._hp;
if (_isEradicated) {
c._age += 10;
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index 757767155c1..c01c86f517e 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -32,12 +32,15 @@ namespace Locations {
#define MAX_LEVEL 200
-const int TRAINING_COSTS1[7] = {
+static const int TRAINING_COSTS1[7] = {
25, 50, 100, 200, 400, 800, 1500
};
-const int TRAINING_COSTS2[7] = {
+static const int TRAINING_COSTS2[7] = {
40, 75, 150, 300, 600, 1200, 2500
};
+static const int CLASS_HP_PER_LEVEL[6] = {
+ 12, 10, 10, 8, 6, 8
+};
Training::Training() : Location("Training") {
}
@@ -49,26 +52,6 @@ bool Training::msgFocus(const FocusMessage &msg) {
return true;
}
-bool Training::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
- leave();
- break;
- case Common::KEYCODE_1:
- case Common::KEYCODE_2:
- case Common::KEYCODE_3:
- case Common::KEYCODE_4:
- case Common::KEYCODE_5:
- case Common::KEYCODE_6:
- changeCharacter(msg.keycode - Common::KEYCODE_1);
- break;
- default:
- break;
- }
-
- return true;
-}
-
void Training::changeCharacter(uint index) {
Location::changeCharacter(index);
Character &c = *g_globals->_currCharacter;
@@ -137,6 +120,99 @@ void Training::draw() {
}
}
+bool Training::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ leave();
+ break;
+ case Common::KEYCODE_a:
+ if (_canTrain)
+ train();
+ break;
+ case Common::KEYCODE_g:
+ gatherGold();
+ redraw();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ changeCharacter(msg.keycode - Common::KEYCODE_1);
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Training::train() {
+ Character &c = *g_globals->_currCharacter;
+
+ if (c._condition) {
+ Sound::sound(SOUND_3);
+ clearSurface();
+ writeString(8, 5, STRING["dialogs.training.condition"]);
+ _timeoutCtr = 3 * FRAME_RATE;
+
+ } else if (!_canAfford) {
+ notEnoughGold();
+
+ } else {
+ // Do the actual training
+ c._gold -= _cost;
+ doTraining();
+ }
+}
+
+void Training::doTraining() {
+ Character &c = *g_globals->_currCharacter;
+ c._level = ++c._levelBase;
+ c._age = ++c._ageBase;
+ if (c._ageBase > 220)
+ c._ageBase = 220;
+ c._v6c += 2;
+
+ int classNum = c._class == NONE ? ROBBER : c._class;
+ int newHP = g_engine->getRandomNumber(CLASS_HP_PER_LEVEL[classNum - 1]);
+
+ if (c._endBase >= 40)
+ newHP += 10;
+ else if (c._endBase >= 35)
+ newHP += 9;
+ else if (c._endBase >= 30)
+ newHP += 8;
+ else if (c._endBase >= 27)
+ newHP += 7;
+ else if (c._endBase >= 24)
+ newHP += 6;
+ else if (c._endBase >= 21)
+ newHP += 5;
+ else if (c._endBase >= 19)
+ newHP += 4;
+ else if (c._endBase >= 17)
+ newHP += 3;
+ else if (c._endBase >= 15)
+ newHP += 2;
+ else if (c._endBase >= 13)
+ newHP += 1;
+ else if (c._endBase >= 9)
+ newHP += 0;
+ else if (c._endBase >= 7)
+ newHP = MAX(newHP - 1, 1);
+ else if (c._endBase >= 5)
+ newHP = MAX(newHP - 2, 1);
+ else
+ newHP = MAX(newHP - 3, 1);
+
+ c._hpBase += newHP;
+ c._hp = c._hpMax = c._hpBase;
+
+ // TODO: Remaining stuff
+}
+
} // namespace Locations
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/training.h b/engines/mm/mm1/views/locations/training.h
index 404b9cdbbe2..2e14f681259 100644
--- a/engines/mm/mm1/views/locations/training.h
+++ b/engines/mm/mm1/views/locations/training.h
@@ -40,6 +40,16 @@ private:
int _cost = 0, _cost2;
bool _canTrain = false;
bool _canAfford = false;
+private:
+ /**
+ * Validates if training is allowed, then trains.
+ */
+ void train();
+
+ /**
+ * Handles training
+ */
+ void doTraining();
protected:
/**
* Change character
Commit: 83209bc81dda4e13d31ef4899024c9190adaa637
https://github.com/scummvm/scummvm/commit/83209bc81dda4e13d31ef4899024c9190adaa637
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Move training code to Character class
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/locations/training.cpp
engines/mm/mm1/views/locations/training.h
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 3dc53822b33..327eefdf1a4 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -21,10 +21,15 @@
#include "common/algorithm.h"
#include "mm/mm1/data/char.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
+static const int CLASS_HP_PER_LEVEL[6] = {
+ 12, 10, 10, 8, 6, 8
+};
+
void Character::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
s.syncAsByte(_sex);
@@ -103,5 +108,50 @@ void Character::clear() {
_v66 = _v67 = _v6c = _v6f = 0;
}
+void Character::increaseLevel() {
+ _level = ++_levelBase;
+ _age = ++_ageBase;
+ if (_ageBase > 220)
+ _ageBase = 220;
+ _v6c += 2;
+
+ int classNum = _class == NONE ? ROBBER : _class;
+ int newHP = g_engine->getRandomNumber(CLASS_HP_PER_LEVEL[classNum - 1]);
+
+ if (_endBase >= 40)
+ newHP += 10;
+ else if (_endBase >= 35)
+ newHP += 9;
+ else if (_endBase >= 30)
+ newHP += 8;
+ else if (_endBase >= 27)
+ newHP += 7;
+ else if (_endBase >= 24)
+ newHP += 6;
+ else if (_endBase >= 21)
+ newHP += 5;
+ else if (_endBase >= 19)
+ newHP += 4;
+ else if (_endBase >= 17)
+ newHP += 3;
+ else if (_endBase >= 15)
+ newHP += 2;
+ else if (_endBase >= 13)
+ newHP += 1;
+ else if (_endBase >= 9)
+ newHP += 0;
+ else if (_endBase >= 7)
+ newHP = MAX(newHP - 1, 1);
+ else if (_endBase >= 5)
+ newHP = MAX(newHP - 2, 1);
+ else
+ newHP = MAX(newHP - 3, 1);
+
+ _hpBase += newHP;
+ _hp = _hpMax = _hpBase;
+
+ // TODO: Remaining stuff
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 9266283b179..68db717c9b2 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -28,6 +28,7 @@ namespace MM {
namespace MM1 {
#define INVENTORY_COUNT 6
+#define MAX_LEVEL 200
enum CharacterClass {
KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
@@ -95,8 +96,20 @@ struct Character {
// Non persistent fields
byte _numDrinks = 0;
+ /**
+ * Handles save/loading a character
+ */
void synchronize(Common::Serializer &s);
+
+ /**
+ * Clearing the character
+ */
void clear();
+
+ /**
+ * Increase the character's level by 1 at a trainer
+ */
+ void increaseLevel();
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index c01c86f517e..bc168fe7b8d 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -22,7 +22,6 @@
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
-#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
namespace MM {
@@ -30,17 +29,12 @@ namespace MM1 {
namespace Views {
namespace Locations {
-#define MAX_LEVEL 200
-
static const int TRAINING_COSTS1[7] = {
25, 50, 100, 200, 400, 800, 1500
};
static const int TRAINING_COSTS2[7] = {
40, 75, 150, 300, 600, 1200, 2500
};
-static const int CLASS_HP_PER_LEVEL[6] = {
- 12, 10, 10, 8, 6, 8
-};
Training::Training() : Location("Training") {
}
@@ -163,56 +157,10 @@ void Training::train() {
} else {
// Do the actual training
c._gold -= _cost;
- doTraining();
+ c.increaseLevel();
}
}
-void Training::doTraining() {
- Character &c = *g_globals->_currCharacter;
- c._level = ++c._levelBase;
- c._age = ++c._ageBase;
- if (c._ageBase > 220)
- c._ageBase = 220;
- c._v6c += 2;
-
- int classNum = c._class == NONE ? ROBBER : c._class;
- int newHP = g_engine->getRandomNumber(CLASS_HP_PER_LEVEL[classNum - 1]);
-
- if (c._endBase >= 40)
- newHP += 10;
- else if (c._endBase >= 35)
- newHP += 9;
- else if (c._endBase >= 30)
- newHP += 8;
- else if (c._endBase >= 27)
- newHP += 7;
- else if (c._endBase >= 24)
- newHP += 6;
- else if (c._endBase >= 21)
- newHP += 5;
- else if (c._endBase >= 19)
- newHP += 4;
- else if (c._endBase >= 17)
- newHP += 3;
- else if (c._endBase >= 15)
- newHP += 2;
- else if (c._endBase >= 13)
- newHP += 1;
- else if (c._endBase >= 9)
- newHP += 0;
- else if (c._endBase >= 7)
- newHP = MAX(newHP - 1, 1);
- else if (c._endBase >= 5)
- newHP = MAX(newHP - 2, 1);
- else
- newHP = MAX(newHP - 3, 1);
-
- c._hpBase += newHP;
- c._hp = c._hpMax = c._hpBase;
-
- // TODO: Remaining stuff
-}
-
} // namespace Locations
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/training.h b/engines/mm/mm1/views/locations/training.h
index 2e14f681259..491a0a74c29 100644
--- a/engines/mm/mm1/views/locations/training.h
+++ b/engines/mm/mm1/views/locations/training.h
@@ -46,10 +46,6 @@ private:
*/
void train();
- /**
- * Handles training
- */
- void doTraining();
protected:
/**
* Change character
Commit: 399fa65016d67ca243aeecd2317d82d29affffd3
https://github.com/scummvm/scummvm/commit/399fa65016d67ca243aeecd2317d82d29affffd3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:55+01:00
Commit Message:
MM: MM1: Remainder of training
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/locations/location.cpp
engines/mm/mm1/views/locations/location.h
engines/mm/mm1/views/locations/statue.cpp
engines/mm/mm1/views/locations/training.cpp
engines/mm/mm1/views/locations/training.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index bb1dafd2324..55ff5ad0dbd 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -170,6 +170,9 @@ dialogs:
cost: "COST %d GOLD"
xp: "EXPERIENCE POINTS"
commence: "A) COMMENCE TRAINING"
+ congrats: "CONGRATULATIONS! YOU ARE NOW LEVEL "
+ hp: "YOU GAINED %d HIT POINTS"
+ new_spells: "YOU GAINED NEW SPELLS!"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 327eefdf1a4..b6ba658161b 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -108,7 +108,7 @@ void Character::clear() {
_v66 = _v67 = _v6c = _v6f = 0;
}
-void Character::increaseLevel() {
+Character::LevelIncrease Character::increaseLevel() {
_level = ++_levelBase;
_age = ++_ageBase;
if (_ageBase > 220)
@@ -150,7 +150,37 @@ void Character::increaseLevel() {
_hpBase += newHP;
_hp = _hpMax = _hpBase;
- // TODO: Remaining stuff
+ int gainedSpells = 0;
+ if (classNum < ARCHER) {
+ if (_levelBase < 7)
+ gainedSpells = 0;
+ else if (_levelBase == 7)
+ gainedSpells = 1;
+ else if (_levelBase == 9)
+ gainedSpells = 2;
+ else if (_levelBase == 11)
+ gainedSpells = 3;
+ else if (_levelBase == 13)
+ gainedSpells = 4;
+ } else if (classNum < SORCERER) {
+ if (_levelBase == 3)
+ gainedSpells = 2;
+ else if (_levelBase == 5)
+ gainedSpells = 3;
+ else if (_levelBase == 7)
+ gainedSpells = 4;
+ else if (_levelBase == 9)
+ gainedSpells = 5;
+ else if (_levelBase == 11)
+ gainedSpells = 6;
+ else if (_levelBase == 13)
+ gainedSpells = 7;
+ }
+
+ LevelIncrease result;
+ result._numHP = newHP;
+ result._numSpells = gainedSpells;
+ return result;
}
} // namespace MM1
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 68db717c9b2..23074e38855 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -109,7 +109,11 @@ struct Character {
/**
* Increase the character's level by 1 at a trainer
*/
- void increaseLevel();
+ struct LevelIncrease {
+ int _numHP;
+ int _numSpells;
+ };
+ LevelIncrease increaseLevel();
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/location.cpp b/engines/mm/mm1/views/locations/location.cpp
index 73cc693a767..0dfa44f2a70 100644
--- a/engines/mm/mm1/views/locations/location.cpp
+++ b/engines/mm/mm1/views/locations/location.cpp
@@ -29,7 +29,7 @@ namespace MM1 {
namespace Views {
namespace Locations {
-#define DISPLAY_TIMEOUT (5 * FRAME_RATE)
+#define DISPLAY_SECONDS 5
Location::Location(const Common::String &name) : TextView(name) {
_bounds = getLineBounds(17, 24);
@@ -51,7 +51,7 @@ void Location::draw() {
void Location::displayMessage(int x, const Common::String &msg) {
clearLines(3, 7);
writeString(x, 5, msg);
- _timeoutCtr = DISPLAY_TIMEOUT;
+ delaySeconds(DISPLAY_SECONDS);
}
void Location::newLine() {
@@ -85,6 +85,10 @@ void Location::notEnoughGold() {
displayMessage(STRING["dialogs.misc.not_enough_gold"]);
}
+void Location::delaySeconds(uint seconds) {
+ _timeoutCtr = seconds * FRAME_RATE;
+}
+
void Location::changeCharacter(uint index) {
if (index >= g_globals->_party.size())
return;
@@ -101,12 +105,16 @@ void Location::leave() {
bool Location::tick() {
if (_timeoutCtr && --_timeoutCtr == 0) {
- redraw();
+ timeout();
}
return TextView::tick();
}
+void Location::timeout() {
+ redraw();
+}
+
} // namespace Locations
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/location.h b/engines/mm/mm1/views/locations/location.h
index 17a3e1b859f..fde271083c3 100644
--- a/engines/mm/mm1/views/locations/location.h
+++ b/engines/mm/mm1/views/locations/location.h
@@ -30,9 +30,10 @@ namespace Views {
namespace Locations {
class Location : public TextView {
+private:
+ int _timeoutCtr = 0;
protected:
Common::String _modeString;
- int _timeoutCtr;
protected:
/**
* Clears the bottom part of the window and
@@ -68,10 +69,21 @@ protected:
*/
void notEnoughGold();
+ /**
+ * Set a delay countdown
+ */
+ void delaySeconds(uint seconds);
+
/**
* Change character
*/
virtual void changeCharacter(uint index);
+
+ /**
+ * Called when an active timeout countdown expired
+ */
+ virtual void timeout();
+
public:
Location(const Common::String &name);
virtual ~Location() {}
@@ -81,6 +93,9 @@ public:
*/
void draw() override;
+ /**
+ * Frame tick
+ */
bool tick() override;
};
diff --git a/engines/mm/mm1/views/locations/statue.cpp b/engines/mm/mm1/views/locations/statue.cpp
index 2bd5ce1ebba..8a588d78233 100644
--- a/engines/mm/mm1/views/locations/statue.cpp
+++ b/engines/mm/mm1/views/locations/statue.cpp
@@ -30,7 +30,7 @@ namespace MM1 {
namespace Views {
namespace Locations {
-#define PAGE1_DELAY (10 * FRAME_RATE)
+#define PAGE1_SECONDS 10
Statue::Statue() : Location("Statue") {
}
@@ -60,7 +60,7 @@ void Statue::draw() {
writeString(STRING["dialogs.statues.plaque"]);
++_pageNum;
- _timeoutCtr = PAGE1_DELAY;
+ delaySeconds(PAGE1_SECONDS);
redraw();
break;
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index bc168fe7b8d..02c4777130b 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -48,6 +48,15 @@ bool Training::msgFocus(const FocusMessage &msg) {
void Training::changeCharacter(uint index) {
Location::changeCharacter(index);
+ checkCharacter();
+}
+
+void Training::timeout() {
+ checkCharacter();
+ Location::timeout();
+}
+
+void Training::checkCharacter() {
Character &c = *g_globals->_currCharacter;
_currLevel = c._levelBase;
@@ -89,7 +98,7 @@ void Training::changeCharacter(uint index) {
}
_remainingExp = _expTotal - c._exp;
- _canTrain = _remainingExp > 0;
+ _canTrain = _remainingExp <= 0;
_canAfford = (int)c._gold >= _cost;
}
@@ -149,7 +158,7 @@ void Training::train() {
Sound::sound(SOUND_3);
clearSurface();
writeString(8, 5, STRING["dialogs.training.condition"]);
- _timeoutCtr = 3 * FRAME_RATE;
+ delaySeconds(3);
} else if (!_canAfford) {
notEnoughGold();
@@ -157,7 +166,21 @@ void Training::train() {
} else {
// Do the actual training
c._gold -= _cost;
- c.increaseLevel();
+ Character::LevelIncrease lvl = c.increaseLevel();
+ Sound::sound(SOUND_2);
+
+ clearSurface();
+ writeString(0, 3, STRING["dialogs.training.congrats"]);
+ writeNumber(c._levelBase);
+
+ writeString(7, 5, Common::String::format(
+ STRING["dialogs.training.hp"].c_str(), lvl._numHP));
+
+ if (lvl._numSpells != 0)
+ writeString(7, 6, STRING["dialogs.training.new_spells"]);
+
+ Sound::sound(SOUND_2);
+ delaySeconds(10);
}
}
diff --git a/engines/mm/mm1/views/locations/training.h b/engines/mm/mm1/views/locations/training.h
index 491a0a74c29..37acf8a5b70 100644
--- a/engines/mm/mm1/views/locations/training.h
+++ b/engines/mm/mm1/views/locations/training.h
@@ -41,6 +41,11 @@ private:
bool _canTrain = false;
bool _canAfford = false;
private:
+ /**
+ * Checks whether a character can train
+ */
+ void checkCharacter();
+
/**
* Validates if training is allowed, then trains.
*/
@@ -52,6 +57,11 @@ protected:
*/
void changeCharacter(uint index) override;
+ /**
+ * Called when an active timeout countdown expired
+ */
+ void timeout() override;
+
public:
Training();
virtual ~Training() {}
Commit: 1db0b37b1938df6aec5cfa0e70b7f8ae3a27caab
https://github.com/scummvm/scummvm/commit/1db0b37b1938df6aec5cfa0e70b7f8ae3a27caab
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: Skeleton subviews for blacksmith buy/sell views
Changed paths:
A engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
A engines/mm/mm1/views/locations/blacksmith_buy_armor.h
A engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
A engines/mm/mm1/views/locations/blacksmith_buy_misc.h
A engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
A engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
A engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
A engines/mm/mm1/views/locations/blacksmith_sell_item.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/locations/blacksmith.cpp
engines/mm/mm1/views/locations/blacksmith.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 55ff5ad0dbd..ee6158d3564 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -10,6 +10,13 @@ dialogs:
buy: "'A'-'F' TO BUY\r(- = CANT USE)"
sell: "'A'-'F' TO SELL"
gather: "'G' GATHER GOLD\r'#' OTHER CHAR"
+ blacksmith:
+ a: "A) BUY WEAPONS"
+ b: "B) BUY ARMOR"
+ c: "C) BUY MISC"
+ d: "D) SELL ITEM"
+ buy:
+ title: "WEAPONS PRICE"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/views/locations/blacksmith.cpp b/engines/mm/mm1/views/locations/blacksmith.cpp
index f7f14f22ff3..06a4890da52 100644
--- a/engines/mm/mm1/views/locations/blacksmith.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith.cpp
@@ -40,6 +40,15 @@ bool Blacksmith::msgFocus(const FocusMessage &msg) {
return true;
}
+void Blacksmith::draw() {
+ Location::draw();
+
+ writeString(22, 1, STRING["dialogs.blacksmith.a"]);
+ writeString(22, 2, STRING["dialogs.blacksmith.b"]);
+ writeString(22, 3, STRING["dialogs.blacksmith.c"]);
+ writeString(22, 4, STRING["dialogs.blacksmith.d"]);
+}
+
bool Blacksmith::msgKeypress(const KeypressMessage &msg) {
switch (msg.keycode) {
case Common::KEYCODE_ESCAPE:
@@ -53,6 +62,18 @@ bool Blacksmith::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_6:
changeCharacter(msg.keycode - Common::KEYCODE_1);
break;
+ case Common::KEYCODE_a:
+ _buyWeapons.addView();
+ break;
+ case Common::KEYCODE_b:
+ buyArmor();
+ break;
+ case Common::KEYCODE_c:
+ buyMisc();
+ break;
+ case Common::KEYCODE_d:
+ sellItem();
+ break;
default:
break;
}
@@ -60,8 +81,20 @@ bool Blacksmith::msgKeypress(const KeypressMessage &msg) {
return true;
}
-void Blacksmith::draw() {
- clearSurface();
+void Blacksmith::buyWeapons() {
+
+}
+
+void Blacksmith::buyArmor() {
+
+}
+
+void Blacksmith::buyMisc() {
+
+}
+
+void Blacksmith::sellItem() {
+
}
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith.h b/engines/mm/mm1/views/locations/blacksmith.h
index 5ff26bc3cd2..7007372087f 100644
--- a/engines/mm/mm1/views/locations/blacksmith.h
+++ b/engines/mm/mm1/views/locations/blacksmith.h
@@ -23,6 +23,10 @@
#define MM1_VIEWS_LOCATIONS_BLACKSMITH_H
#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/views/locations/blacksmith_buy_weapons.h"
+#include "mm/mm1/views/locations/blacksmith_buy_armor.h"
+#include "mm/mm1/views/locations/blacksmith_buy_misc.h"
+#include "mm/mm1/views/locations/blacksmith_sell_item.h"
namespace MM {
namespace MM1 {
@@ -30,6 +34,32 @@ namespace Views {
namespace Locations {
class Blacksmith : public Location {
+private:
+ BlacksmithBuyWeapons _buyWeapons;
+ BlacksmithBuyArmor _buyArmor;
+ BlacksmithBuyMisc _buyMisc;
+ BlacksmithSellItem _sellItem;
+private:
+ /**
+ * Buy weapons
+ */
+ void buyWeapons();
+
+ /**
+ * Buy armor
+ */
+ void buyArmor();
+
+ /**
+ * Buy misc items
+ */
+ void buyMisc();
+
+ /**
+ * Sell an item
+ */
+ void sellItem();
+
public:
Blacksmith();
virtual ~Blacksmith() {}
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
new file mode 100644
index 00000000000..231ce113f26
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/locations/blacksmith_buy_armor.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+BlacksmithBuyArmor::BlacksmithBuyArmor() :
+ Location("BlacksmithBuyArmor") {
+ _modeString = STRING["dialogs.location.buy"];
+}
+
+void BlacksmithBuyArmor::draw() {
+ Location::draw();
+
+ writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+}
+
+bool BlacksmithBuyArmor::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ close();
+ break;
+ case Common::KEYCODE_a:
+ case Common::KEYCODE_b:
+ case Common::KEYCODE_c:
+ case Common::KEYCODE_d:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_f:
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_armor.h b/engines/mm/mm1/views/locations/blacksmith_buy_armor.h
new file mode 100644
index 00000000000..0e2e179a19e
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_armor.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_ARMOR_H
+#define MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_ARMOR_H
+
+#include "mm/mm1/views/locations/location.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+class BlacksmithBuyArmor : public Location {
+public:
+ BlacksmithBuyArmor();
+ virtual ~BlacksmithBuyArmor() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
new file mode 100644
index 00000000000..7cfebd767ad
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/locations/blacksmith_buy_misc.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+BlacksmithBuyMisc::BlacksmithBuyMisc() :
+ Location("BlacksmithBuyMisc") {
+ _modeString = STRING["dialogs.location.buy"];
+}
+
+void BlacksmithBuyMisc::draw() {
+ Location::draw();
+
+ writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+}
+
+bool BlacksmithBuyMisc::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ close();
+ break;
+ case Common::KEYCODE_a:
+ case Common::KEYCODE_b:
+ case Common::KEYCODE_c:
+ case Common::KEYCODE_d:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_f:
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_misc.h b/engines/mm/mm1/views/locations/blacksmith_buy_misc.h
new file mode 100644
index 00000000000..1dc4b7ac2e1
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_misc.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_MISC_H
+#define MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_MISC_H
+
+#include "mm/mm1/views/locations/location.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+class BlacksmithBuyMisc : public Location {
+public:
+ BlacksmithBuyMisc();
+ virtual ~BlacksmithBuyMisc() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
new file mode 100644
index 00000000000..3261f50a5a4
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/locations/blacksmith_buy_weapons.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+BlacksmithBuyWeapons::BlacksmithBuyWeapons() :
+ Location("BlacksmithBuyWeapons") {
+ _modeString = STRING["dialogs.location.buy"];
+}
+
+void BlacksmithBuyWeapons::draw() {
+ Location::draw();
+
+ writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+}
+
+bool BlacksmithBuyWeapons::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ close();
+ break;
+ case Common::KEYCODE_a:
+ case Common::KEYCODE_b:
+ case Common::KEYCODE_c:
+ case Common::KEYCODE_d:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_f:
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
new file mode 100644
index 00000000000..902c0f6ef33
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_WEAPONS_H
+#define MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_WEAPONS_H
+
+#include "mm/mm1/views/locations/location.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+class BlacksmithBuyWeapons : public Location {
+public:
+ BlacksmithBuyWeapons();
+ virtual ~BlacksmithBuyWeapons() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
new file mode 100644
index 00000000000..c8faebb598f
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/locations/blacksmith_sell_item.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+BlacksmithSellItem::BlacksmithSellItem() :
+ Location("BlacksmithSellItem") {
+ _modeString = STRING["dialogs.location.sell"];
+}
+
+void BlacksmithSellItem::draw() {
+ Location::draw();
+
+ writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+}
+
+bool BlacksmithSellItem::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ close();
+ break;
+ case Common::KEYCODE_a:
+ case Common::KEYCODE_b:
+ case Common::KEYCODE_c:
+ case Common::KEYCODE_d:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_f:
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.h b/engines/mm/mm1/views/locations/blacksmith_sell_item.h
new file mode 100644
index 00000000000..7fe174e5556
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_SELL_ITEM_H
+#define MM1_VIEWS_LOCATIONS_BLACKSMITH_SELL_ITEM_H
+
+#include "mm/mm1/views/locations/location.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+class BlacksmithSellItem : public Location {
+public:
+ BlacksmithSellItem();
+ virtual ~BlacksmithSellItem() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index fe128f3e45c..f285c761dc7 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -25,6 +25,10 @@ MODULE_OBJS := \
mm1/utils/strings.o \
mm1/views/locations/location.o \
mm1/views/locations/blacksmith.o \
+ mm1/views/locations/blacksmith_buy_weapons.o \
+ mm1/views/locations/blacksmith_buy_armor.o \
+ mm1/views/locations/blacksmith_buy_misc.o \
+ mm1/views/locations/blacksmith_sell_item.o \
mm1/views/locations/market.o \
mm1/views/locations/statue.o \
mm1/views/locations/tavern.o \
Commit: 63117d1ab02a11c70d33c4446a29e27bc5d25216
https://github.com/scummvm/scummvm/commit/63117d1ab02a11c70d33c4446a29e27bc5d25216
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: Fixed shadowed field
Changed paths:
engines/mm/mm1/messages.h
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 6366573dcff..bfcdbda9f5b 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -87,8 +87,8 @@ struct InfoMessage : public Message {
Line() {}
Line(const Common::String &text) :
Common::Point(-1, -1), _text(text) {}
- Line(int x, int y, const Common::String &text) :
- Common::Point(x, y), _text(text) {}
+ Line(int x1, int y1, const Common::String &text) :
+ Common::Point(x1, y1), _text(text) {}
};
Common::Array<Line> _lines;
YNCallback _ynCallback = nullptr;
Commit: 3ebf0f8a8fefe1c91cde8109417a91bbb03eb298
https://github.com/scummvm/scummvm/commit/3ebf0f8a8fefe1c91cde8109417a91bbb03eb298
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: Move location data arrays to a new file
Changed paths:
A engines/mm/mm1/data/locations.h
engines/mm/mm1/views/locations/blacksmith.cpp
engines/mm/mm1/views/locations/market.cpp
engines/mm/mm1/views/locations/market.h
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/locations/temple.h
engines/mm/mm1/views/locations/training.cpp
engines/mm/mm1/views/locations/training.h
diff --git a/engines/mm/mm1/data/locations.h b/engines/mm/mm1/data/locations.h
new file mode 100644
index 00000000000..44b4b7dc665
--- /dev/null
+++ b/engines/mm/mm1/data/locations.h
@@ -0,0 +1,57 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_LOCATIONS_H
+#define MM1_DATA_LOCATIONS_H
+
+#include "common/serializer.h"
+
+namespace MM {
+namespace MM1 {
+
+struct MarketData {
+ const byte FOOD_COST[4] = { 5, 10, 20, 200 };
+};
+
+struct TempleData {
+ const uint16 HEAL_COST1[5] = { 2000, 5000, 5000, 2000, 8000 };
+ const uint16 HEAL_COST2[5] = { 200, 500, 500, 200, 1000 };
+ const uint16 HEAL_COST3[5] = { 25, 50, 50, 25, 100 };
+ const uint16 UNCURSE_COST[5] = { 500, 1000, 1000, 1012, 1500 };
+ const uint16 ALIGNMENT_COST[5] = { 250, 200, 200, 200, 250 };
+ const uint16 DONATE_COST[5] = { 100, 100, 100, 25, 200 };
+ const byte ALIGNMENT_VALS[3] = { 8, 0x10, 0x18 };
+ const byte DONATE_VALS[5] = { 1, 2, 4, 8, 0x10 };
+};
+
+struct TrainingData {
+ const int TRAINING_COSTS1[7] = {
+ 25, 50, 100, 200, 400, 800, 1500
+ };
+ const int TRAINING_COSTS2[7] = {
+ 40, 75, 150, 300, 600, 1200, 2500
+ };
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/locations/blacksmith.cpp b/engines/mm/mm1/views/locations/blacksmith.cpp
index 06a4890da52..5b5c89a216c 100644
--- a/engines/mm/mm1/views/locations/blacksmith.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith.cpp
@@ -66,13 +66,13 @@ bool Blacksmith::msgKeypress(const KeypressMessage &msg) {
_buyWeapons.addView();
break;
case Common::KEYCODE_b:
- buyArmor();
+ _buyArmor.addView();
break;
case Common::KEYCODE_c:
- buyMisc();
+ _buyMisc.addView();
break;
case Common::KEYCODE_d:
- sellItem();
+ _sellItem.addView();
break;
default:
break;
@@ -81,22 +81,6 @@ bool Blacksmith::msgKeypress(const KeypressMessage &msg) {
return true;
}
-void Blacksmith::buyWeapons() {
-
-}
-
-void Blacksmith::buyArmor() {
-
-}
-
-void Blacksmith::buyMisc() {
-
-}
-
-void Blacksmith::sellItem() {
-
-}
-
} // namespace Locations
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/market.cpp b/engines/mm/mm1/views/locations/market.cpp
index 4fe84e76c74..1dafe54e491 100644
--- a/engines/mm/mm1/views/locations/market.cpp
+++ b/engines/mm/mm1/views/locations/market.cpp
@@ -33,8 +33,6 @@ namespace Locations {
#define TOTAL_FOOD 40
#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
-static const byte FOOD_COST[4] = { 5, 10, 20, 200 };
-
Market::Market() : Location("Market") {
_bounds = getLineBounds(21, 24);
}
diff --git a/engines/mm/mm1/views/locations/market.h b/engines/mm/mm1/views/locations/market.h
index 4eb6504e14b..e5b72231d4a 100644
--- a/engines/mm/mm1/views/locations/market.h
+++ b/engines/mm/mm1/views/locations/market.h
@@ -24,13 +24,14 @@
#include "mm/mm1/data/char.h"
#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/data/locations.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Locations {
-class Market : public Location {
+class Market : public Location, public MarketData {
private:
int _foodCost = 0;
int _displayCtr = 0;
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 8b2e645905f..e30cdcb68b9 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -30,15 +30,6 @@ namespace MM1 {
namespace Views {
namespace Locations {
-static const uint16 HEAL_COST1[5] = { 2000, 5000, 5000, 2000, 8000 };
-static const uint16 HEAL_COST2[5] = { 200, 500, 500, 200, 1000 };
-static const uint16 HEAL_COST3[5] = { 25, 50, 50, 25, 100 };
-static const uint16 UNCURSE_COST[5] = { 500, 1000, 1000, 1012, 1500 };
-static const uint16 ALIGNMENT_COST[5] = { 250, 200, 200, 200, 250 };
-static const uint16 DONATE_COST[5] = { 100, 100, 100, 25, 200 };
-static const byte ALIGNMENT_VALS[3] = { 8, 0x10, 0x18 };
-static const byte DONATE_VALS[5] = { 1, 2, 4, 8, 0x10 };
-
Temple::Temple() : Location("Temple") {
}
diff --git a/engines/mm/mm1/views/locations/temple.h b/engines/mm/mm1/views/locations/temple.h
index 43e9dcbec36..9bcae5b5996 100644
--- a/engines/mm/mm1/views/locations/temple.h
+++ b/engines/mm/mm1/views/locations/temple.h
@@ -23,13 +23,14 @@
#define MM1_VIEWS_LOCATIONS_TEMPLE_H
#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/data/locations.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Locations {
-class Temple : public Location {
+class Temple : public Location, public TempleData {
private:
bool _isEradicated = false;
int _healCost = 0, _uncurseCost = 0;
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index 02c4777130b..523f4e0c93c 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -29,13 +29,6 @@ namespace MM1 {
namespace Views {
namespace Locations {
-static const int TRAINING_COSTS1[7] = {
- 25, 50, 100, 200, 400, 800, 1500
-};
-static const int TRAINING_COSTS2[7] = {
- 40, 75, 150, 300, 600, 1200, 2500
-};
-
Training::Training() : Location("Training") {
}
diff --git a/engines/mm/mm1/views/locations/training.h b/engines/mm/mm1/views/locations/training.h
index 37acf8a5b70..b3375c0c072 100644
--- a/engines/mm/mm1/views/locations/training.h
+++ b/engines/mm/mm1/views/locations/training.h
@@ -24,13 +24,14 @@
#include "mm/mm1/data/char.h"
#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/data/locations.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Locations {
-class Training : public Location {
+class Training : public Location, public TrainingData {
private:
int _currLevel = 0;
CharacterClass _class = KNIGHT;
Commit: 511a1eb829a5083694581eafd5b5bc7ec5d5ed74
https://github.com/scummvm/scummvm/commit/511a1eb829a5083694581eafd5b5bc7ec5d5ed74
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: Implementing blacksmith buy weapons
Changed paths:
engines/mm/mm1/data/locations.h
engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
diff --git a/engines/mm/mm1/data/locations.h b/engines/mm/mm1/data/locations.h
index 44b4b7dc665..d3dd379babf 100644
--- a/engines/mm/mm1/data/locations.h
+++ b/engines/mm/mm1/data/locations.h
@@ -27,6 +27,10 @@
namespace MM {
namespace MM1 {
+struct BlacksmithData {
+
+};
+
struct MarketData {
const byte FOOD_COST[4] = { 5, 10, 20, 200 };
};
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
index 902c0f6ef33..9b36e8b0081 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
@@ -23,13 +23,14 @@
#define MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_WEAPONS_H
#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/data/locations.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Locations {
-class BlacksmithBuyWeapons : public Location {
+class BlacksmithBuyWeapons : public Location, public BlacksmithData {
public:
BlacksmithBuyWeapons();
virtual ~BlacksmithBuyWeapons() {}
Commit: 8a5dcd489714a6b0e38180ea69991b10d03a89da
https://github.com/scummvm/scummvm/commit/8a5dcd489714a6b0e38180ea69991b10d03a89da
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: Implementing blacksmith subviews
Changed paths:
A engines/mm/mm1/views/locations/blacksmith_subview.cpp
A engines/mm/mm1/views/locations/blacksmith_subview.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/data/items.h
engines/mm/mm1/data/locations.h
engines/mm/mm1/views/locations/blacksmith.h
engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
engines/mm/mm1/views/locations/blacksmith_buy_armor.h
engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
engines/mm/mm1/views/locations/blacksmith_buy_misc.h
engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
engines/mm/mm1/views/locations/blacksmith_sell_item.h
engines/mm/mm1/views/locations/location.cpp
engines/mm/mm1/views/locations/location.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ee6158d3564..1c86ab14eae 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -15,8 +15,11 @@ dialogs:
b: "B) BUY ARMOR"
c: "C) BUY MISC"
d: "D) SELL ITEM"
- buy:
- title: "WEAPONS PRICE"
+ armor: "ARMOR PRICE"
+ weapons: "WEAPONS PRICE"
+ misc: "MISC PRICE"
+ backpack: "BACKPACK PRICE"
+ thankyou: "THANK YOU!"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
@@ -215,6 +218,7 @@ dialogs:
no_characters: "NO AVAILABLE CHARACTERS"
some_characters: "AVAILABLE CHARACTERS"
not_enough_gold: "*** NOT ENOUGH GOLD ***"
+ full: "*** BACKPACK FULL ***"
stats:
none: "NONE"
inventory: "-----<EQUIPPED>----------<BACKPACK>----".
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index b6ba658161b..76cb4ed3038 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -183,5 +183,28 @@ Character::LevelIncrease Character::increaseLevel() {
return result;
}
+Character::BuyResult Character::buyItem(byte itemId) {
+ getItem(itemId);
+
+ // Check if backpack is full
+ int slotIndex = 0;
+ while (slotIndex < INVENTORY_COUNT && _backpack[slotIndex])
+ ++slotIndex;
+ if (slotIndex == INVENTORY_COUNT)
+ return BUY_BACKPACK_FULL;
+
+ // Check character has enough gold
+ Item &item = g_globals->_currItem;
+ if (_gold < item._cost)
+ return BUY_NOT_ENOUGH_GOLD;
+
+ // Add the item
+ _gold -= item._cost;
+ _backpack[slotIndex] = itemId;
+ _backpack14[slotIndex] = item._field14;
+
+ return BUY_SUCCESS;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 23074e38855..f8316942a77 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -89,6 +89,8 @@ struct Character {
uint8 _equipped[INVENTORY_COUNT] = { 0 };
uint8 _backpack[INVENTORY_COUNT] = { 0 };
+ uint8 _backpack14[INVENTORY_COUNT] = { 0 };
+
// TODO: Figure out what these are
int _v58, _v59, _v62, _v63, _v64, _v65;
int _v66, _v67, _v6c, _v6e, _v6f;
@@ -114,6 +116,12 @@ struct Character {
int _numSpells;
};
LevelIncrease increaseLevel();
+
+ /**
+ * Buy an item
+ */
+ enum BuyResult { BUY_SUCCESS, BUY_NOT_ENOUGH_GOLD, BUY_BACKPACK_FULL };
+ BuyResult buyItem(byte itemId);
};
} // namespace MM1
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 6ba110ba240..615ad1d0715 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -29,7 +29,13 @@ namespace MM1 {
struct Item {
Common::String _name;
+ byte _enablement;
byte _field10;
+ byte _field11;
+ byte _field14;
+ uint16 _cost;
+ byte _field17;
+ byte _field18;
};
extern const Item ITEMS1[];
diff --git a/engines/mm/mm1/data/locations.h b/engines/mm/mm1/data/locations.h
index d3dd379babf..291d4d998dc 100644
--- a/engines/mm/mm1/data/locations.h
+++ b/engines/mm/mm1/data/locations.h
@@ -28,7 +28,43 @@ namespace MM {
namespace MM1 {
struct BlacksmithData {
+ const byte BLACKSMITH_CLASS_USAGE[6] = { 0x20, 0x10, 8, 4, 2, 1 };
+};
+
+struct BuyWeaponData {
+ const byte WEAPONS_TOWN1[6] = { 2, 3, 5, 61, 62, 86 };
+ const byte WEAPONS_TOWN2[6] = { 4, 6, 8, 63, 87, 88 };
+ const byte WEAPONS_TOWN3[6] = { 9, 10, 62, 64, 89, 91 };
+ const byte WEAPONS_TOWN4[6] = { 23, 67, 69, 93, 97, 99 };
+ const byte WEAPONS_TOWN5[6] = { 7, 11, 64, 65, 90, 92 };
+ const byte *WEAPONS[5] = {
+ WEAPONS_TOWN1, WEAPONS_TOWN2, WEAPONS_TOWN3,
+ WEAPONS_TOWN4, WEAPONS_TOWN5
+ };
+};
+struct BuyArmorData {
+ const byte ARMOR_TOWN1[6] = { 156, 121, 122, 123, 124, 125 };
+ const byte ARMOR_TOWN2[6] = { 156, 157, 121, 122, 123, 124 };
+ const byte ARMOR_TOWN3[6] = { 157, 121, 124, 125, 126, 127 };
+ const byte ARMOR_TOWN4[6] = { 160, 128, 131, 132, 133, 134 };
+ const byte ARMOR_TOWN5[6] = { 157, 123, 124, 125, 126, 127 };
+ const byte *ARMOR[5] = {
+ ARMOR_TOWN1, ARMOR_TOWN2, ARMOR_TOWN3,
+ ARMOR_TOWN4, ARMOR_TOWN5
+ };
+};
+
+struct BuyMiscData {
+ const byte MISC_TOWN1[6] = { 172, 171, 175, 178, 185, 192 };
+ const byte MISC_TOWN2[6] = { 172, 171, 174, 183, 188, 195 };
+ const byte MISC_TOWN3[6] = { 173, 175, 176, 179, 184, 195 };
+ const byte MISC_TOWN4[6] = { 180, 196, 211, 215, 219, 223 };
+ const byte MISC_TOWN5[6] = { 171, 173, 177, 185, 186, 192 };
+ const byte *MISC[5] = {
+ MISC_TOWN1, MISC_TOWN2, MISC_TOWN3,
+ MISC_TOWN4, MISC_TOWN5
+ };
};
struct MarketData {
diff --git a/engines/mm/mm1/views/locations/blacksmith.h b/engines/mm/mm1/views/locations/blacksmith.h
index 7007372087f..d7e0f2204bb 100644
--- a/engines/mm/mm1/views/locations/blacksmith.h
+++ b/engines/mm/mm1/views/locations/blacksmith.h
@@ -39,27 +39,6 @@ private:
BlacksmithBuyArmor _buyArmor;
BlacksmithBuyMisc _buyMisc;
BlacksmithSellItem _sellItem;
-private:
- /**
- * Buy weapons
- */
- void buyWeapons();
-
- /**
- * Buy armor
- */
- void buyArmor();
-
- /**
- * Buy misc items
- */
- void buyMisc();
-
- /**
- * Sell an item
- */
- void sellItem();
-
public:
Blacksmith();
virtual ~Blacksmith() {}
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
index 231ce113f26..e810bc909c5 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
@@ -31,33 +31,24 @@ namespace Views {
namespace Locations {
BlacksmithBuyArmor::BlacksmithBuyArmor() :
- Location("BlacksmithBuyArmor") {
+ BlacksmithSubview("BlacksmithBuyArmor") {
_modeString = STRING["dialogs.location.buy"];
}
-void BlacksmithBuyArmor::draw() {
- Location::draw();
+bool BlacksmithBuyArmor::msgFocus(const FocusMessage &msg) {
+ int townNum = g_maps->_currentMap->dataByte(0);
+ if (townNum < 1 || townNum >= 6)
+ townNum = 1;
+ _items = ARMOR[townNum - 1];
- writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+ return true;
}
-bool BlacksmithBuyArmor::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
- close();
- break;
- case Common::KEYCODE_a:
- case Common::KEYCODE_b:
- case Common::KEYCODE_c:
- case Common::KEYCODE_d:
- case Common::KEYCODE_e:
- case Common::KEYCODE_f:
- break;
- default:
- break;
- }
+void BlacksmithBuyArmor::draw() {
+ Location::draw();
- return true;
+ writeString(23, 1, STRING["dialogs.blacksmith.armor"]);
+ drawItems();
}
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_armor.h b/engines/mm/mm1/views/locations/blacksmith_buy_armor.h
index 0e2e179a19e..27ee3011441 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_armor.h
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_armor.h
@@ -22,20 +22,21 @@
#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_ARMOR_H
#define MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_ARMOR_H
-#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/views/locations/blacksmith_subview.h"
+#include "mm/mm1/data/locations.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Locations {
-class BlacksmithBuyArmor : public Location {
+class BlacksmithBuyArmor : public BlacksmithSubview, public BuyArmorData {
public:
BlacksmithBuyArmor();
virtual ~BlacksmithBuyArmor() {}
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgFocus(const FocusMessage &msg) override;
};
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
index 7cfebd767ad..5136a6d7248 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
@@ -31,33 +31,24 @@ namespace Views {
namespace Locations {
BlacksmithBuyMisc::BlacksmithBuyMisc() :
- Location("BlacksmithBuyMisc") {
+ BlacksmithSubview("BlacksmithBuyMisc") {
_modeString = STRING["dialogs.location.buy"];
}
-void BlacksmithBuyMisc::draw() {
- Location::draw();
+bool BlacksmithBuyMisc::msgFocus(const FocusMessage &msg) {
+ int townNum = g_maps->_currentMap->dataByte(0);
+ if (townNum < 1 || townNum >= 6)
+ townNum = 1;
+ _items = MISC[townNum - 1];
- writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+ return true;
}
-bool BlacksmithBuyMisc::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
- close();
- break;
- case Common::KEYCODE_a:
- case Common::KEYCODE_b:
- case Common::KEYCODE_c:
- case Common::KEYCODE_d:
- case Common::KEYCODE_e:
- case Common::KEYCODE_f:
- break;
- default:
- break;
- }
+void BlacksmithBuyMisc::draw() {
+ Location::draw();
- return true;
+ writeString(23, 1, STRING["dialogs.blacksmith.misc"]);
+ drawItems();
}
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_misc.h b/engines/mm/mm1/views/locations/blacksmith_buy_misc.h
index 1dc4b7ac2e1..9718ebf41cc 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_misc.h
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_misc.h
@@ -22,20 +22,21 @@
#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_MISC_H
#define MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_MISC_H
-#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/views/locations/blacksmith_subview.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Locations {
-class BlacksmithBuyMisc : public Location {
+class BlacksmithBuyMisc : public BlacksmithSubview,
+ public BuyMiscData {
public:
BlacksmithBuyMisc();
virtual ~BlacksmithBuyMisc() {}
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgFocus(const FocusMessage &msg) override;
};
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
index 3261f50a5a4..6c517e430d7 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
@@ -31,33 +31,24 @@ namespace Views {
namespace Locations {
BlacksmithBuyWeapons::BlacksmithBuyWeapons() :
- Location("BlacksmithBuyWeapons") {
+ BlacksmithSubview("BlacksmithBuyWeapons") {
_modeString = STRING["dialogs.location.buy"];
}
-void BlacksmithBuyWeapons::draw() {
- Location::draw();
+bool BlacksmithBuyWeapons::msgFocus(const FocusMessage &msg) {
+ int townNum = g_maps->_currentMap->dataByte(0);
+ if (townNum < 1 || townNum >= 6)
+ townNum = 1;
+ _items = WEAPONS[townNum - 1];
- writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+ return true;
}
-bool BlacksmithBuyWeapons::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
- close();
- break;
- case Common::KEYCODE_a:
- case Common::KEYCODE_b:
- case Common::KEYCODE_c:
- case Common::KEYCODE_d:
- case Common::KEYCODE_e:
- case Common::KEYCODE_f:
- break;
- default:
- break;
- }
+void BlacksmithBuyWeapons::draw() {
+ Location::draw();
- return true;
+ writeString(23, 1, STRING["dialogs.blacksmith.weapons"]);
+ drawItems();
}
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
index 9b36e8b0081..f5ba6cab544 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.h
@@ -22,7 +22,7 @@
#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_WEAPONS_H
#define MM1_VIEWS_LOCATIONS_BLACKSMITH_BUY_WEAPONS_H
-#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/views/locations/blacksmith_subview.h"
#include "mm/mm1/data/locations.h"
namespace MM {
@@ -30,13 +30,13 @@ namespace MM1 {
namespace Views {
namespace Locations {
-class BlacksmithBuyWeapons : public Location, public BlacksmithData {
+class BlacksmithBuyWeapons : public BlacksmithSubview, public BuyWeaponData {
public:
BlacksmithBuyWeapons();
virtual ~BlacksmithBuyWeapons() {}
+ bool msgFocus(const FocusMessage &msg) override;
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index c8faebb598f..0b2fe0f09b7 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -31,33 +31,23 @@ namespace Views {
namespace Locations {
BlacksmithSellItem::BlacksmithSellItem() :
- Location("BlacksmithSellItem") {
+ BlacksmithSubview("BlacksmithSellItem") {
_modeString = STRING["dialogs.location.sell"];
}
void BlacksmithSellItem::draw() {
Location::draw();
- writeString(23, 1, STRING["dialogs.blacksmith.buy.title"]);
+ writeString(23, 1, STRING["dialogs.blacksmith.backpack"]);
+ drawItems();
}
-bool BlacksmithSellItem::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
- close();
- break;
- case Common::KEYCODE_a:
- case Common::KEYCODE_b:
- case Common::KEYCODE_c:
- case Common::KEYCODE_d:
- case Common::KEYCODE_e:
- case Common::KEYCODE_f:
- break;
- default:
- break;
- }
+void BlacksmithSellItem::drawItems() {
+ // TODO
+}
- return true;
+void BlacksmithSellItem::selectItem(uint index) {
+ // TODO
}
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.h b/engines/mm/mm1/views/locations/blacksmith_sell_item.h
index 7fe174e5556..28774efcc02 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.h
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.h
@@ -22,20 +22,27 @@
#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_SELL_ITEM_H
#define MM1_VIEWS_LOCATIONS_BLACKSMITH_SELL_ITEM_H
-#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/views/locations/blacksmith_subview.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Locations {
-class BlacksmithSellItem : public Location {
+class BlacksmithSellItem : public BlacksmithSubview {
+private:
+ void drawItems();
+protected:
+ /**
+ * Selects an item from the list
+ */
+ void selectItem(uint index) override;
+
public:
BlacksmithSellItem();
virtual ~BlacksmithSellItem() {}
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_subview.cpp b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
new file mode 100644
index 00000000000..0005f4b91d8
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/locations/blacksmith_subview.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+void BlacksmithSubview::drawItems() {
+ for (int idx = 0; idx < INVENTORY_COUNT; ++idx) {
+ writeChar(17, 1, 'A' + idx);
+ writeString(") ");
+
+ getItem(_items[idx]);
+ drawIsAllowed();
+ writeString(g_globals->_currItem._name);
+ _textPos.x = 35;
+ writeNumber(g_globals->_currItem._cost);
+ }
+}
+
+void BlacksmithSubview::drawIsAllowed() {
+ Character &c = *g_globals->_currCharacter;
+
+ if (c._class != NONE && c._class <= ROBBER) {
+ if (!(BLACKSMITH_CLASS_USAGE[c._class - 1] &
+ g_globals->_currItem._enablement))
+ return;
+ }
+
+ _textPos.x--;
+ writeChar('-');
+}
+
+bool BlacksmithSubview::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ close();
+ break;
+ case Common::KEYCODE_a:
+ case Common::KEYCODE_b:
+ case Common::KEYCODE_c:
+ case Common::KEYCODE_d:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_f:
+ selectItem(msg.keycode - Common::KEYCODE_a);
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void BlacksmithSubview::selectItem(uint index) {
+ switch (g_globals->_currCharacter->buyItem(
+ _items[index])) {
+ case Character::BUY_BACKPACK_FULL:
+ backpackFull();
+ break;
+ case Character::BUY_NOT_ENOUGH_GOLD:
+ notEnoughGold();
+ break;
+ default:
+ // Purchased successfully
+ clearSurface();
+ displayMessage(15, STRING["dialogs.blacksmith.thankyou"]);
+ break;
+ }
+}
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/locations/blacksmith_subview.h b/engines/mm/mm1/views/locations/blacksmith_subview.h
new file mode 100644
index 00000000000..8fac8ced4bf
--- /dev/null
+++ b/engines/mm/mm1/views/locations/blacksmith_subview.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_LOCATIONS_BLACKSMITH_SUBVIEW_H
+#define MM1_VIEWS_LOCATIONS_BLACKSMITH_SUBVIEW_H
+
+#include "mm/mm1/views/locations/location.h"
+#include "mm/mm1/data/locations.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Locations {
+
+class BlacksmithSubview : public Location, public BlacksmithData {
+protected:
+ const byte *_items = nullptr;
+private:
+ /**
+ * For an item draws the character if the item is
+ * not allowed for the character's class
+ */
+ void drawIsAllowed();
+protected:
+ /**
+ * Draws a list of items
+ */
+ void drawItems();
+
+ /**
+ * Selects an item from the list
+ */
+ virtual void selectItem(uint index);
+public:
+ BlacksmithSubview(const Common::String &name) : Location(name) {}
+
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Locations
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/locations/location.cpp b/engines/mm/mm1/views/locations/location.cpp
index 0dfa44f2a70..46a21c2b62d 100644
--- a/engines/mm/mm1/views/locations/location.cpp
+++ b/engines/mm/mm1/views/locations/location.cpp
@@ -85,6 +85,11 @@ void Location::notEnoughGold() {
displayMessage(STRING["dialogs.misc.not_enough_gold"]);
}
+void Location::backpackFull() {
+ Sound::sound(SOUND_2);
+ displayMessage(STRING["dialogs.misc.backpack_full"]);
+}
+
void Location::delaySeconds(uint seconds) {
_timeoutCtr = seconds * FRAME_RATE;
}
diff --git a/engines/mm/mm1/views/locations/location.h b/engines/mm/mm1/views/locations/location.h
index fde271083c3..4c135570c5f 100644
--- a/engines/mm/mm1/views/locations/location.h
+++ b/engines/mm/mm1/views/locations/location.h
@@ -69,6 +69,11 @@ protected:
*/
void notEnoughGold();
+ /**
+ * Displays backpack is full
+ */
+ void backpackFull();
+
/**
* Set a delay countdown
*/
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index f285c761dc7..2acbb5b9de5 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -25,6 +25,7 @@ MODULE_OBJS := \
mm1/utils/strings.o \
mm1/views/locations/location.o \
mm1/views/locations/blacksmith.o \
+ mm1/views/locations/blacksmith_subview.o \
mm1/views/locations/blacksmith_buy_weapons.o \
mm1/views/locations/blacksmith_buy_armor.o \
mm1/views/locations/blacksmith_buy_misc.o \
Commit: 5016905f8081e47f4efc6fb6c8d29e9545009643
https://github.com/scummvm/scummvm/commit/5016905f8081e47f4efc6fb6c8d29e9545009643
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: Fix compiler warnings
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/quick_ref.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index aa04858e54b..1fe896c6c19 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -131,7 +131,7 @@ bool Console::cmdMapString(int argc, const char **argv) {
Common::File f;
if (argc != 3) {
- debugPrintf("%s <map Id> <offset>\n");
+ debugPrintf("%s <map Id> <offset>\n", argv[0]);
} else {
int mapId = strToInt(argv[1]);
Maps::Map *map = g_globals->_maps.getMap(mapId);
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 85949534b07..dfd6db4fc54 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -100,6 +100,8 @@ void CreateCharacters::NewCharacter::save() {
setHP(8);
re._v6c = 50;
break;
+ default:
+ break;
}
switch (_race) {
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 8c09353be73..ee9ef1777d1 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -55,6 +55,8 @@ bool Game::msgAction(const ActionMessage &msg) {
case KEYBIND_SEARCH:
MM1::Game::Search::execute();
break;
+ default:
+ break;
}
return TextView::msgAction(msg);
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 34cda7d3738..e792cb18a24 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -94,6 +94,8 @@ bool QuickRef::msgAction(const ActionMessage &msg) {
case KEYBIND_QUICKREF:
addView();
return true;
+ default:
+ break;
}
return false;
Commit: 1398295cf0e0a1f1739b23624e1acd735f85a3de
https://github.com/scummvm/scummvm/commit/1398295cf0e0a1f1739b23624e1acd735f85a3de
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: Fix clashing town enums
Changed paths:
engines/mm/mm1/data/char.h
engines/mm/mm1/data/roster.cpp
engines/mm/mm1/data/roster.h
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/create_characters.cpp
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index f8316942a77..65dc994266e 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -54,11 +54,6 @@ enum Condition {
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
};
-enum Town {
- NO_TOWN = 0, SORPIGAL = 1, PORTSMITH = 2, ALGARY = 3,
- DUSK = 4, ERLIQUIN = 5
-};
-
struct Character {
char _name[16] = { 0 };
Sex _sex = MALE;
diff --git a/engines/mm/mm1/data/roster.cpp b/engines/mm/mm1/data/roster.cpp
index f5808238d25..1a80e324cc4 100644
--- a/engines/mm/mm1/data/roster.cpp
+++ b/engines/mm/mm1/data/roster.cpp
@@ -70,7 +70,7 @@ void Roster::remove(Character *entry) {
entry->clear();
size_t idx = entry - _items;
- _towns[idx] = NO_TOWN;
+ _towns[idx] = Maps::NO_TOWN;
}
bool Roster::empty() const {
diff --git a/engines/mm/mm1/data/roster.h b/engines/mm/mm1/data/roster.h
index f5edefbdf0b..90dacf095da 100644
--- a/engines/mm/mm1/data/roster.h
+++ b/engines/mm/mm1/data/roster.h
@@ -24,6 +24,7 @@
#include "common/serializer.h"
#include "mm/mm1/data/char.h"
+#include "mm/mm1/maps/maps.h"
namespace MM {
namespace MM1 {
@@ -35,7 +36,7 @@ private:
Common::String rosterSaveName() const;
public:
Character _items[ROSTER_COUNT];
- Town _towns[ROSTER_COUNT] = { NO_TOWN };
+ Maps::TownId _towns[ROSTER_COUNT] = { Maps::NO_TOWN };
Character &operator[](uint idx) {
assert(idx < ROSTER_COUNT);
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 2e8ac565af6..555b218bfc1 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -32,8 +32,8 @@ namespace MM1 {
namespace Maps {
enum TownId {
- SORPIGAL = 1, PORTSMITH = 2, ALGARY = 3,
- DUSK = 4, ERLIQUIN = 5
+ NO_TOWN = 0, SORPIGAL = 1, PORTSMITH = 2,
+ ALGARY = 3, DUSK = 4, ERLIQUIN = 5
};
enum DirMask {
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index dfd6db4fc54..f81af480acf 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -62,7 +62,7 @@ void CreateCharacters::NewCharacter::save() {
while (i < ROSTER_COUNT && g_globals->_roster._towns[i])
++i;
- g_globals->_roster._towns[i] = SORPIGAL;
+ g_globals->_roster._towns[i] = Maps::SORPIGAL;
g_globals->_currCharacter = &g_globals->_roster[i];
Character &re = *g_globals->_currCharacter;
re.clear();
Commit: 3fb611c25c6bcd5dfb22e420ff9568460ebd165d
https://github.com/scummvm/scummvm/commit/3fb611c25c6bcd5dfb22e420ff9568460ebd165d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:56+01:00
Commit Message:
MM: MM1: In-progress implement sell items dialog
Changed paths:
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index 0b2fe0f09b7..454ea6605fe 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -38,16 +38,43 @@ BlacksmithSellItem::BlacksmithSellItem() :
void BlacksmithSellItem::draw() {
Location::draw();
- writeString(23, 1, STRING["dialogs.blacksmith.backpack"]);
+ writeString(22, 1, STRING["dialogs.blacksmith.backpack"]);
drawItems();
}
void BlacksmithSellItem::drawItems() {
- // TODO
+ // TODO: List items to sell
+ for (int idx = 0; idx < INVENTORY_COUNT; ++idx) {
+
+ }
}
void BlacksmithSellItem::selectItem(uint index) {
- // TODO
+ Character &c = *g_globals->_currCharacter;
+ int itemIndex = index;
+
+ // Some slots may be empty, so we need to iterate
+ // until we found the index'ed filled in slot
+ for (index = 0; index < INVENTORY_COUNT ; ++index) {
+ if (c._backpack[index]) {
+ if (--itemIndex == 0)
+ break;
+ }
+ }
+ if (index == INVENTORY_COUNT)
+ return;
+
+ // Clear the slot
+ int itemId = c._backpack[index];
+ c._backpack[index] = 0;
+ int v14 = c._backpack14[index];
+ c._backpack14[index] = 0;
+
+ getItem(itemId);
+ if (!v14 && g_globals->_currItem._field14)
+ g_globals->_currItem._cost /= 2;
+
+ c._gold += g_globals->_currItem._cost / 2;
}
} // namespace Locations
Commit: b627ba61ed88c68e4243e9e4ad0dfb415d506bea
https://github.com/scummvm/scummvm/commit/b627ba61ed88c68e4243e9e4ad0dfb415d506bea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:57+01:00
Commit Message:
MM: MM1: Add automap data to roster save file
Changed paths:
engines/mm/mm1/data/roster.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/data/roster.cpp b/engines/mm/mm1/data/roster.cpp
index 1a80e324cc4..b04b8b88e4e 100644
--- a/engines/mm/mm1/data/roster.cpp
+++ b/engines/mm/mm1/data/roster.cpp
@@ -43,6 +43,14 @@ void Roster::load() {
if (sf) {
Common::Serializer s(sf, nullptr);
synchronize(s);
+
+ while (!sf->eos()) {
+ uint32 chunk = sf->readUint32BE();
+ if (chunk == MKTAG('M', 'A', 'P', 'S')) {
+ sf->skip(4); // Skip chunk size
+ g_maps->synchronize(s);
+ }
+ }
} else {
Common::File f;
if (!f.open("roster.dta"))
@@ -58,6 +66,17 @@ void Roster::save() {
rosterSaveName());
Common::Serializer s(nullptr, sf);
synchronize(s);
+
+ // Get automap data to save
+ Common::MemoryWriteStreamDynamic mapData(DisposeAfterUse::YES);
+ Common::Serializer s2(nullptr, &mapData);
+ g_maps->synchronize(s2);
+
+ // Write out the map data
+ sf->writeUint32BE(MKTAG('M', 'A', 'P', 'S'));
+ sf->writeUint32LE(mapData.size());
+ sf->write(mapData.getData(), mapData.size());
+
delete sf;
}
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 8eb88325706..85c86c18582 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -66,7 +66,7 @@ private:
public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
- bool _visited[MAP_SIZE];
+ uint8 _visited[MAP_SIZE];
public:
Map(uint index, const Common::String &name, uint16 id);
virtual ~Map() {}
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 12a16efc456..91bec804bc4 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -208,6 +208,17 @@ void Maps::load(uint mapId) {
Common::fill(&_data1[0], &_data1[32], 0);
}
+void Maps::synchronize(Common::Serializer &s) {
+ // Store a count of the number of maps,
+ // just in case new ones are added in later
+ uint8 mapCount = _maps.size();
+ s.syncAsByte(mapCount);
+
+ for (uint8 i = 0; i < mapCount; ++mapCount) {
+ s.syncBytes(_maps[i]->_visited, MAP_SIZE);
+ }
+}
+
void Maps::select(uint16 id, byte section) {
uint mapId = getIndex(id, section);
load(mapId);
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 555b218bfc1..bf8499f39d1 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -105,6 +105,11 @@ public:
*/
void load(uint mapId);
+ /**
+ * Loads or saves map data
+ */
+ void synchronize(Common::Serializer &s);
+
/**
* Selects a map
*/
Commit: cffa41c0e6b2ae26b9c52d2c375b69f332306896
https://github.com/scummvm/scummvm/commit/cffa41c0e6b2ae26b9c52d2c375b69f332306896
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:57+01:00
Commit Message:
MM: MM1: Implement signing into inn
Changed paths:
A engines/mm/mm1/views/locations/inn.cpp
A engines/mm/mm1/views/locations/inn.h
R engines/mm/mm1/views/inn.cpp
R engines/mm/mm1/views/inn.h
engines/mm/mm1/data/char.h
engines/mm/mm1/data/roster.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views_enh/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 65dc994266e..486d8feb5a8 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -98,6 +98,13 @@ struct Character {
*/
void synchronize(Common::Serializer &s);
+ /**
+ * Equality test
+ */
+ bool operator==(const Character &rhs) const {
+ return !strcmp(_name, rhs._name);
+ }
+
/**
* Clearing the character
*/
diff --git a/engines/mm/mm1/data/roster.cpp b/engines/mm/mm1/data/roster.cpp
index b04b8b88e4e..551876300c0 100644
--- a/engines/mm/mm1/data/roster.cpp
+++ b/engines/mm/mm1/data/roster.cpp
@@ -77,6 +77,7 @@ void Roster::save() {
sf->writeUint32LE(mapData.size());
sf->write(mapData.getData(), mapData.size());
+ sf->finalize();
delete sf;
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 075cc22897e..95ab783d988 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -27,7 +27,6 @@
#include "mm/utils/strings_data.h"
#include "mm/xeen/sprites.h"
#include "mm/mm1/data/game_state.h"
-#include "mm/mm1/data/int_array.h"
#include "mm/mm1/data/items.h"
#include "mm/mm1/data/roster.h"
#include "mm/mm1/maps/maps.h"
@@ -42,7 +41,6 @@ public:
Character *_currCharacter = nullptr;
Item _currItem;
Maps::TownId _startingTown = Maps::SORPIGAL;
- IntArray _partyChars;
Maps::Maps _maps;
bool _intangible = false; // Console flag
BitmapFont _font;
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 71c500b268f..3700ee14faa 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -58,7 +58,13 @@ void Map00::special() {
}
void Map00::special00() {
-
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map00.inn_inside"],
+ []() {
+ g_events->replaceView("Inn");
+ }
+ ));
}
void Map00::special01() {
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 3e21de0b11d..a37b6708ab0 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -26,7 +26,6 @@
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/create_characters.h"
#include "mm/mm1/views/game.h"
-#include "mm/mm1/views/inn.h"
#include "mm/mm1/views/main_menu.h"
#include "mm/mm1/views/order.h"
#include "mm/mm1/views/protect.h"
@@ -34,6 +33,7 @@
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/view_characters.h"
#include "mm/mm1/views/locations/blacksmith.h"
+#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/views/locations/market.h"
#include "mm/mm1/views/locations/statue.h"
#include "mm/mm1/views/locations/tavern.h"
@@ -49,7 +49,6 @@ private:
Views::AreYouReady _areYouReady;
Views::CreateCharacters _createCharacters;
Views::Game _game;
- Views::Inn _inn;
Views::MainMenu _mainMenu;
Views::Order _order;
Views::Protect _protect;
@@ -58,6 +57,7 @@ private:
Views::ViewCharacters _viewCharacters;
Views::ViewCharacter _viewCharacter;
Views::Locations::Blacksmith _blacksmith;
+ Views::Locations::Inn _inn;
Views::Locations::Market _market;
Views::Locations::Statue _statue;
Views::Locations::Tavern _tavern;
diff --git a/engines/mm/mm1/views/inn.cpp b/engines/mm/mm1/views/locations/inn.cpp
similarity index 78%
rename from engines/mm/mm1/views/inn.cpp
rename to engines/mm/mm1/views/locations/inn.cpp
index 09c19e6c8ad..fcf271b5b27 100644
--- a/engines/mm/mm1/views/inn.cpp
+++ b/engines/mm/mm1/views/locations/inn.cpp
@@ -19,14 +19,18 @@
*
*/
-#include "mm/mm1/views/inn.h"
+#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/globals.h"
namespace MM {
namespace MM1 {
namespace Views {
+namespace Locations {
bool Inn::msgFocus(const FocusMessage &msg) {
+ // Save the roster
+ g_globals->_roster.save();
+
// Get a list of characters in the town
_charNums.clear();
for (uint i = 0; i < ROSTER_COUNT; ++i) {
@@ -34,6 +38,18 @@ bool Inn::msgFocus(const FocusMessage &msg) {
_charNums.push_back(i);
}
+ // Build up a list of characters in the party
+ // (for if we're opening the inn from in-game)
+ _partyChars.clear();
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ for (uint j = 0; j < ROSTER_COUNT; ++j) {
+ if (g_globals->_roster[j] == g_globals->_party[i]) {
+ _partyChars.push_back(j);
+ break;
+ }
+ }
+ }
+
return true;
}
@@ -60,7 +76,7 @@ void Inn::draw() {
Common::Point(20, 6 + idx - 9);
// Write character
- writeChar(g_globals->_partyChars.contains(charNum) ? '@' : ' ');
+ writeChar(_partyChars.contains(charNum) ? '@' : ' ');
writeChar('A' + idx);
writeChar(')');
writeString(re._name);
@@ -74,9 +90,9 @@ void Inn::draw() {
writeString(range);
writeString(STRING["dialogs.inn.add_remove"]);
- if (!g_globals->_partyChars.empty())
+ if (!_partyChars.empty())
writeString(13, 22, STRING["dialogs.inn.exit"]);
- if (g_globals->_partyChars.size() == 6)
+ if (_partyChars.size() == 6)
writeString(10, 16, STRING["dialogs.inn.full"]);
}
}
@@ -86,15 +102,15 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
replaceView("MainMenu");
return true;
} else if (msg.keycode >= Common::KEYCODE_a &&
- msg.keycode < (Common::KeyCode)(Common::KEYCODE_a + _charNums.size())) {
+ msg.keycode < (Common::KeyCode)(Common::KEYCODE_a + _charNums.size())) {
int charNum = _charNums[msg.keycode - Common::KEYCODE_a];
if (msg.flags & Common::KBD_CTRL) {
// Toggle in party
- if (g_globals->_partyChars.contains(charNum))
- g_globals->_partyChars.remove(charNum);
+ if (_partyChars.contains(charNum))
+ _partyChars.remove(charNum);
else
- g_globals->_partyChars.push_back(charNum);
+ _partyChars.push_back(charNum);
redraw();
@@ -106,9 +122,9 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
} else if (msg.keycode == Common::KEYCODE_x) {
// Load party from selected characters
g_globals->_party.clear();
- for (uint i = 0; i < g_globals->_partyChars.size(); ++i)
+ for (uint i = 0; i < _partyChars.size(); ++i)
g_globals->_party.push_back(
- g_globals->_roster[g_globals->_partyChars[i]]);
+ g_globals->_roster[_partyChars[i]]);
// Load the given town
g_globals->_maps.loadTown(g_globals->_startingTown);
@@ -117,6 +133,7 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
return false;
}
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/inn.h b/engines/mm/mm1/views/locations/inn.h
similarity index 84%
rename from engines/mm/mm1/views/inn.h
rename to engines/mm/mm1/views/locations/inn.h
index 47963d61894..6a054521f79 100644
--- a/engines/mm/mm1/views/inn.h
+++ b/engines/mm/mm1/views/locations/inn.h
@@ -19,27 +19,33 @@
*
*/
-#ifndef MM1_VIEWS_INN_H
-#define MM1_VIEWS_INN_H
+#ifndef MM1_VIEWS_LOCATIONS_INN_H
+#define MM1_VIEWS_LOCATIONS_INN_H
#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/data/int_array.h"
namespace MM {
namespace MM1 {
namespace Views {
+namespace Locations {
class Inn : public TextView {
private:
Common::Array<uint> _charNums;
+ IntArray _partyChars;
public:
- Inn() : TextView("Inn") {}
- virtual ~Inn() {}
+ Inn() : TextView("Inn") {
+ }
+ virtual ~Inn() {
+ }
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
+} // namespace Locations
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index 0ab12680c3e..c5238391941 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -25,7 +25,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/create_characters.h"
-#include "mm/mm1/views/inn.h"
+#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/views/main_menu.h"
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
@@ -44,7 +44,7 @@ private:
// Unenhanced views
Views::AreYouReady _areYouReady;
Views::CreateCharacters _createCharacters;
- Views::Inn _inn;
+ Views::Locations::Inn _inn;
Views::MainMenu _mainMenu;
Views::Protect _protect;
Views::QuickRef _quickRef;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 2acbb5b9de5..e088ea7cc24 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -30,6 +30,7 @@ MODULE_OBJS := \
mm1/views/locations/blacksmith_buy_armor.o \
mm1/views/locations/blacksmith_buy_misc.o \
mm1/views/locations/blacksmith_sell_item.o \
+ mm1/views/locations/inn.o \
mm1/views/locations/market.o \
mm1/views/locations/statue.o \
mm1/views/locations/tavern.o \
@@ -42,7 +43,6 @@ MODULE_OBJS := \
mm1/views/game_messages.o \
mm1/views/game_party.o \
mm1/views/game_view.o \
- mm1/views/inn.o \
mm1/views/main_menu.o \
mm1/views/order.o \
mm1/views/protect.o \
Commit: 425f778f73107f8bdf31cf210dc58c03d96c6875
https://github.com/scummvm/scummvm/commit/425f778f73107f8bdf31cf210dc58c03d96c6875
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:57+01:00
Commit Message:
MM: MM1: Splitting up character display classes
Changed paths:
A engines/mm/mm1/views/character_base.cpp
A engines/mm/mm1/views/character_base.h
A engines/mm/mm1/views/character_manage.cpp
A engines/mm/mm1/views/character_manage.h
A engines/mm/mm1/views/characters.cpp
A engines/mm/mm1/views/characters.h
R engines/mm/mm1/views/view_characters.cpp
R engines/mm/mm1/views/view_characters.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/quick_ref.cpp
engines/mm/mm1/views/quick_ref.h
engines/mm/mm1/views_enh/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/view_characters.cpp b/engines/mm/mm1/views/character_base.cpp
similarity index 56%
rename from engines/mm/mm1/views/view_characters.cpp
rename to engines/mm/mm1/views/character_base.cpp
index 79f033621d6..82b8881a763 100644
--- a/engines/mm/mm1/views/view_characters.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/views/character_base.h"
#include "mm/mm1/utils/strings.h"
#include "mm/mm1/globals.h"
@@ -27,68 +27,7 @@ namespace MM {
namespace MM1 {
namespace Views {
-void ViewCharacters::draw() {
- drawTextBorder();
-
- Roster &roster = g_globals->_roster;
- writeString(11, 0, STRING["dialogs.view_characters.title"]);
- int lineNum = 0;
- _charIndexes.clear();
-
- if (g_globals->_roster.empty()) {
- writeString(8, 5, STRING["dialogs.misc.no_characters"]);
- escToGoBack();
- return;
- }
-
- // Loop to print characters
- for (int charNum = 0; charNum < 18; ++charNum) {
- if (roster._towns[charNum]) {
- const Character &re = roster[charNum];
- Common::String charName = re._name;
- pad_string(charName, 16, '.');
-
- Common::String level = Common::String::format("(%d)L%d",
- roster._towns[charNum], re._level);
- pad_string(level, 7);
-
- Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
- STRING[Common::String::format("stats.classes.%d", (int)re._class)] :
- STRING["stats.none"];
-
- // Form line like: A) charName...(1)L1 Knight
- Common::String line = Common::String::format("(%c) %s%s%s",
- 'A' + lineNum, charName.c_str(), level.c_str(), className.c_str());
- writeString(3, 3 + lineNum++, line);
-
- _charIndexes.push_back(charNum);
- }
- }
-
- // Print legend at the bottom
- writeString(6, 22, Common::String::format(
- STRING["dialogs.view_characters.legend1"].c_str(),
- 'A' + (int)_charIndexes.size() - 1));
- writeString(12, 24, STRING["dialogs.misc.go_back"]);
-}
-
-bool ViewCharacters::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_ESCAPE) {
- close();
- } else if (msg.keycode >= Common::KEYCODE_a &&
- msg.keycode <= (Common::KEYCODE_a + (int)_charIndexes.size() - 1)) {
- // Character selected
- uint charIndex = _charIndexes[msg.keycode - Common::KEYCODE_a];
- g_globals->_currCharacter = &g_globals->_roster[charIndex];
- addView("ViewCharacter");
- }
-
- return false;
-}
-
-/*------------------------------------------------------------------------*/
-
-void CharacterStats::printStats() {
+void CharacterBase::printStats() {
Character &re = *g_globals->_currCharacter;
printSummary();
@@ -163,7 +102,7 @@ void CharacterStats::printStats() {
printInventory();
}
-void CharacterStats::printSummary() {
+void CharacterBase::printSummary() {
Character &re = *g_globals->_currCharacter;
writeString(1, 0, re._name);
@@ -189,7 +128,7 @@ void CharacterStats::printSummary() {
writeString(32, 0, STRING["stats.none"]);
}
-void CharacterStats::printCondition() {
+void CharacterBase::printCondition() {
Character &re = *g_globals->_currCharacter;
writeString(STRING["stats.attributes.cond"]);
_textPos.x++;
@@ -228,7 +167,7 @@ void CharacterStats::printCondition() {
}
}
-void CharacterStats::printInventory() {
+void CharacterBase::printInventory() {
Character &re = *g_globals->_currCharacter;
writeString(0, 12, STRING["stats.inventory"]);
@@ -252,99 +191,10 @@ void CharacterStats::printInventory() {
}
}
-/*------------------------------------------------------------------------*/
-
-void ViewCharacter::draw() {
+void CharacterBase::draw() {
assert(g_globals->_currCharacter);
clearSurface();
printStats();
-
- switch (_state) {
- case DISPLAY:
- writeString(6, 21, STRING["dialogs.view_character.rename"]);
- writeString(6, 22, STRING["dialogs.view_character.delete"]);
- escToGoBack();
- break;
-
- case RENAME:
- writeString(6, 21, STRING["dialogs.view_character.name"]);
- writeString(_newName);
- writeChar('_');
- break;
-
- case DELETE:
- writeString(6, 21, STRING["dialogs.view_character.are_you_sure"]);
- break;
- }
-}
-
-bool ViewCharacter::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_ESCAPE) {
- if (_state != DISPLAY) {
- redraw();
- } else {
- close();
- }
-
- _state = DISPLAY;
- return true;
- }
-
- switch (_state) {
- case DISPLAY:
- if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_n) {
- _state = RENAME;
- _newName = "";
- redraw();
- } else if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_d) {
- _state = DELETE;
- redraw();
- }
- break;
-
- case RENAME:
- if (msg.ascii >= 32 && msg.ascii <= 127) {
- _newName += toupper(msg.ascii);
- redraw();
- }
- if (msg.keycode == Common::KEYCODE_RETURN || _newName.size() == 15) {
- strncpy(g_globals->_currCharacter->_name, _newName.c_str(), 16);
- _state = DISPLAY;
- redraw();
- } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
- !_newName.empty()) {
- _newName.deleteLastChar();
- redraw();
- }
- break;
-
- case DELETE:
- if (msg.keycode == Common::KEYCODE_y) {
- // Removes the character and returns to View All Characters
- g_globals->_roster.remove(g_globals->_currCharacter);
- close();
- } else {
- // Any other keypress returns to display mode
- redraw();
- }
-
- _state = DISPLAY;
- break;
- }
-
- return true;
-}
-
-bool ViewCharacter::msgAction(const ActionMessage &msg) {
- if (msg._action >= KEYBIND_VIEW_PARTY1 &&
- msg._action <= KEYBIND_VIEW_PARTY6) {
- g_globals->_currCharacter = &g_globals->_party[
- msg._action - KEYBIND_VIEW_PARTY1];
- addView();
- return true;
- }
-
- return false;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/character_base.h b/engines/mm/mm1/views/character_base.h
new file mode 100644
index 00000000000..008f2093198
--- /dev/null
+++ b/engines/mm/mm1/views/character_base.h
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_VIEW_CHARACTER_BASE_H
+#define MM1_VIEWS_VIEW_CHARACTER_BASE_H
+
+#include "common/array.h"
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+/**
+ * Base class for showing character information.
+ * MM1 has three character dialogs:
+ * 1) Character management from Create Characters
+ * 2) Inn that allows simply viewing characters
+ * 3) In-game character display
+ */
+class CharacterBase : public TextView {
+private:
+ void printStats();
+ void printSummary();
+ void printInventory();
+protected:
+ void printCondition();
+
+public:
+ CharacterBase(const Common::String &name) : TextView(name) {}
+ ~CharacterBase() {}
+
+ void draw() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/character_manage.cpp b/engines/mm/mm1/views/character_manage.cpp
new file mode 100644
index 00000000000..454b558cb7e
--- /dev/null
+++ b/engines/mm/mm1/views/character_manage.cpp
@@ -0,0 +1,125 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/character_manage.h"
+#include "mm/mm1/utils/strings.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void CharacterManage::draw() {
+ assert(g_globals->_currCharacter);
+ CharacterBase::draw();
+
+ switch (_state) {
+ case DISPLAY:
+ writeString(6, 21, STRING["dialogs.view_character.rename"]);
+ writeString(6, 22, STRING["dialogs.view_character.delete"]);
+ escToGoBack();
+ break;
+
+ case RENAME:
+ writeString(6, 21, STRING["dialogs.view_character.name"]);
+ writeString(_newName);
+ writeChar('_');
+ break;
+
+ case DELETE:
+ writeString(6, 21, STRING["dialogs.view_character.are_you_sure"]);
+ break;
+ }
+}
+
+bool CharacterManage::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ if (_state != DISPLAY) {
+ redraw();
+ } else {
+ close();
+ }
+
+ _state = DISPLAY;
+ return true;
+ }
+
+ switch (_state) {
+ case DISPLAY:
+ if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_n) {
+ _state = RENAME;
+ _newName = "";
+ redraw();
+ } else if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_d) {
+ _state = DELETE;
+ redraw();
+ }
+ break;
+
+ case RENAME:
+ if (msg.ascii >= 32 && msg.ascii <= 127) {
+ _newName += toupper(msg.ascii);
+ redraw();
+ }
+ if (msg.keycode == Common::KEYCODE_RETURN || _newName.size() == 15) {
+ strncpy(g_globals->_currCharacter->_name, _newName.c_str(), 16);
+ _state = DISPLAY;
+ redraw();
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
+ !_newName.empty()) {
+ _newName.deleteLastChar();
+ redraw();
+ }
+ break;
+
+ case DELETE:
+ if (msg.keycode == Common::KEYCODE_y) {
+ // Removes the character and returns to View All Characters
+ g_globals->_roster.remove(g_globals->_currCharacter);
+ close();
+ } else {
+ // Any other keypress returns to display mode
+ redraw();
+ }
+
+ _state = DISPLAY;
+ break;
+ }
+
+ return true;
+}
+
+bool CharacterManage::msgAction(const ActionMessage &msg) {
+ if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6 &&
+ _state == DISPLAY) {
+ g_globals->_currCharacter = &g_globals->_party[
+ msg._action - KEYBIND_VIEW_PARTY1];
+ addView();
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/view_characters.h b/engines/mm/mm1/views/character_manage.h
similarity index 59%
rename from engines/mm/mm1/views/view_characters.h
rename to engines/mm/mm1/views/character_manage.h
index ddf232ec309..e520ddbdb47 100644
--- a/engines/mm/mm1/views/view_characters.h
+++ b/engines/mm/mm1/views/character_manage.h
@@ -19,55 +19,26 @@
*
*/
-#ifndef MM1_VIEWS_VIEW_CHARACTERS_H
-#define MM1_VIEWS_VIEW_CHARACTERS_H
+#ifndef MM1_VIEWS_CHARACTER_MANAGE_H
+#define MM1_VIEWS_CHARACTER_MANAGE_H
#include "common/array.h"
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/character_base.h"
namespace MM {
namespace MM1 {
namespace Views {
/**
- * Dialog for View All Characters
+ * Character management dialog
*/
-class ViewCharacters : public TextView {
-private:
- Common::Array<uint> _charIndexes;
-public:
- ViewCharacters() : TextView("ViewCharacters") {}
- virtual ~ViewCharacters() {}
-
- void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
-};
-
-/**
- * Base class for showing character information
- */
-class CharacterStats : public TextView {
-protected:
- void printStats();
- void printSummary();
- void printCondition();
- void printInventory();
-
-public:
- CharacterStats(const Common::String &name) : TextView(name) {}
- ~CharacterStats() {}
-};
-
-/**
- * Dialog for showing the stats for a single character.
- */
-class ViewCharacter : public CharacterStats {
+class CharacterManage : public CharacterBase {
enum ViewState { DISPLAY = 0, RENAME = 1, DELETE = 2 };
ViewState _state = DISPLAY;
Common::String _newName;
public:
- ViewCharacter() : CharacterStats("ViewCharacter") {}
- virtual ~ViewCharacter() {}
+ CharacterManage() : CharacterBase("CharacterManage") {}
+ virtual ~CharacterManage() {}
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
diff --git a/engines/mm/mm1/views/characters.cpp b/engines/mm/mm1/views/characters.cpp
new file mode 100644
index 00000000000..0190de61d38
--- /dev/null
+++ b/engines/mm/mm1/views/characters.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/characters.h"
+#include "mm/mm1/utils/strings.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void Characters::draw() {
+ drawTextBorder();
+
+ Roster &roster = g_globals->_roster;
+ writeString(11, 0, STRING["dialogs.view_characters.title"]);
+ int lineNum = 0;
+ _charIndexes.clear();
+
+ if (g_globals->_roster.empty()) {
+ writeString(8, 5, STRING["dialogs.misc.no_characters"]);
+ escToGoBack();
+ return;
+ }
+
+ // Loop to print characters
+ for (int charNum = 0; charNum < 18; ++charNum) {
+ if (roster._towns[charNum]) {
+ const Character &re = roster[charNum];
+ Common::String charName = re._name;
+ pad_string(charName, 16, '.');
+
+ Common::String level = Common::String::format("(%d)L%d",
+ roster._towns[charNum], re._level);
+ pad_string(level, 7);
+
+ Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
+ STRING[Common::String::format("stats.classes.%d", (int)re._class)] :
+ STRING["stats.none"];
+
+ // Form line like: A) charName...(1)L1 Knight
+ Common::String line = Common::String::format("(%c) %s%s%s",
+ 'A' + lineNum, charName.c_str(), level.c_str(), className.c_str());
+ writeString(3, 3 + lineNum++, line);
+
+ _charIndexes.push_back(charNum);
+ }
+ }
+
+ // Print legend at the bottom
+ writeString(6, 22, Common::String::format(
+ STRING["dialogs.view_characters.legend1"].c_str(),
+ 'A' + (int)_charIndexes.size() - 1));
+ writeString(12, 24, STRING["dialogs.misc.go_back"]);
+}
+
+bool Characters::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ } else if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode <= (Common::KEYCODE_a + (int)_charIndexes.size() - 1)) {
+ // Character selected
+ uint charIndex = _charIndexes[msg.keycode - Common::KEYCODE_a];
+ g_globals->_currCharacter = &g_globals->_roster[charIndex];
+ addView("ViewCharacter");
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/characters.h b/engines/mm/mm1/views/characters.h
new file mode 100644
index 00000000000..ea274a26095
--- /dev/null
+++ b/engines/mm/mm1/views/characters.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_CHARACTERS_H
+#define MM1_VIEWS_CHARACTERS_H
+
+#include "common/array.h"
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+/**
+ * Dialog for View All Characters
+ */
+class Characters : public TextView {
+private:
+ Common::Array<uint> _charIndexes;
+public:
+ Characters() : TextView("Characters") {}
+ virtual ~Characters() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index a37b6708ab0..529943b13d3 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -31,7 +31,8 @@
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
-#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/views/character_manage.h"
+#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/views/locations/market.h"
@@ -54,8 +55,9 @@ private:
Views::Protect _protect;
Views::QuickRef _quickRef;
Views::Title _title;
- Views::ViewCharacters _viewCharacters;
- Views::ViewCharacter _viewCharacter;
+// Views::ViewCharacters _viewCharacters;
+ Views::CharacterManage _characterManage;
+
Views::Locations::Blacksmith _blacksmith;
Views::Locations::Inn _inn;
Views::Locations::Market _market;
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index e792cb18a24..29d779450b2 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -101,8 +101,6 @@ bool QuickRef::msgAction(const ActionMessage &msg) {
return false;
}
-
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/quick_ref.h b/engines/mm/mm1/views/quick_ref.h
index fae67baacf7..03cdffec995 100644
--- a/engines/mm/mm1/views/quick_ref.h
+++ b/engines/mm/mm1/views/quick_ref.h
@@ -22,15 +22,18 @@
#ifndef MM1_VIEWS_QUICK_REF_H
#define MM1_VIEWS_QUICK_REF_H
-#include "mm/mm1/views/view_characters.h"
+#include "mm/mm1/views/character_base.h"
namespace MM {
namespace MM1 {
namespace Views {
-class QuickRef : public CharacterStats {
+/**
+ * Quick reference list of all the characters.
+ */
+class QuickRef : public CharacterBase {
public:
- QuickRef() : CharacterStats("QuickRef") {}
+ QuickRef() : CharacterBase("QuickRef") {}
virtual ~QuickRef() {}
void draw() override;
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index c5238391941..365675719fd 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -30,7 +30,7 @@
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
-#include "mm/mm1/views/view_characters.h"
+//#include "mm/mm1/views/char.h"
#include "mm/mm1/views_enh/game.h"
namespace MM {
@@ -49,8 +49,8 @@ private:
Views::Protect _protect;
Views::QuickRef _quickRef;
Views::Title _title;
- Views::ViewCharacters _viewCharacters;
- Views::ViewCharacter _viewCharacter;
+// Views::ViewCharacters _viewCharacters;
+// Views::ViewCharacter _viewCharacter;
public:
Dialogs() {}
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index e088ea7cc24..cd682a4e886 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -37,6 +37,9 @@ MODULE_OBJS := \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
mm1/views/are_you_ready.o \
+ mm1/views/character_base.o \
+ mm1/views/character_manage.o \
+ mm1/views/characters.o \
mm1/views/create_characters.o \
mm1/views/game.o \
mm1/views/game_commands.o \
@@ -50,7 +53,6 @@ MODULE_OBJS := \
mm1/views/statue.o \
mm1/views/title.o \
mm1/views/text_view.o \
- mm1/views/view_characters.o \
mm1/views_enh/button_container.o \
mm1/views_enh/dialogs.o \
mm1/views_enh/game.o \
Commit: 0d642f71df298b5a325d7b161b2cae90fc224ef3
https://github.com/scummvm/scummvm/commit/0d642f71df298b5a325d7b161b2cae90fc224ef3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:57+01:00
Commit Message:
MM: MM1: Beginnings of in-game character info
Changed paths:
A engines/mm/mm1/views/character_info.cpp
A engines/mm/mm1/views/character_info.h
A engines/mm/mm1/views/character_view.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/meta_engine.cpp
engines/mm/mm1/views/character_base.cpp
engines/mm/mm1/views/character_base.h
engines/mm/mm1/views/characters.cpp
engines/mm/mm1/views/characters.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/locations/inn.cpp
engines/mm/mm1/views/locations/inn.h
engines/mm/mm1/views/quick_ref.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 1c86ab14eae..fe99cfd6933 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -20,6 +20,11 @@ dialogs:
misc: "MISC PRICE"
backpack: "BACKPACK PRICE"
thankyou: "THANK YOU!"
+ character:
+ legend1: "'Q' QUICK REF 'C' CAST 'R' REMOVE"
+ legend2: " # VIEW OTHER 'D' DISCARD 'S' SHARE"
+ legend3: " 'E' EQUIP 'T' TRADE"
+ legend4: "'ESC' TO GO BACK 'G' GATHER 'U' USE"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 522d34c2249..45398e91b53 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -107,7 +107,7 @@ void Events::replaceView(UIElement *ui) {
assert(ui);
if (!_views.empty()) {
focusedView()->msgUnfocus(UnfocusMessage());
- _views.clear();
+ _views.pop();
}
_views.push(ui);
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 90d07497031..7bcaf103ccf 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -188,6 +188,7 @@ protected:
bool msg##NAME(const NAME##Message &e) override { \
return !_views.empty() ? focusedView()->msg##NAME(e) : false; \
}
+ MESSAGE(Action);
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(Keypress);
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index 5d547dbe7ff..7c611d7c5c6 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -37,7 +37,13 @@ struct KeybindingRecord {
};
static const KeybindingRecord MENU_KEYS[] = {
- { KEYBIND_ESCAPE, "ESCPAE", "Escape", "ESC", nullptr },
+ { KEYBIND_ESCAPE, "ESCAPE", "Escape", "ESC", nullptr },
+ { KEYBIND_VIEW_PARTY1, "PARTY1", "View Party Member 1", "1", nullptr },
+ { KEYBIND_VIEW_PARTY2, "PARTY2", "View Party Member 2", "2", nullptr },
+ { KEYBIND_VIEW_PARTY3, "PARTY3", "View Party Member 3", "3", nullptr },
+ { KEYBIND_VIEW_PARTY4, "PARTY4", "View Party Member 4", "4", nullptr },
+ { KEYBIND_VIEW_PARTY5, "PARTY5", "View Party Member 5", "5", nullptr },
+ { KEYBIND_VIEW_PARTY6, "PARTY6", "View Party Member 6", "6", nullptr },
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
};
diff --git a/engines/mm/mm1/views/character_base.cpp b/engines/mm/mm1/views/character_base.cpp
index 82b8881a763..9e05b98f26f 100644
--- a/engines/mm/mm1/views/character_base.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -197,6 +197,15 @@ void CharacterBase::draw() {
printStats();
}
+bool CharacterBase::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ return true;
+ }
+
+ return false;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/character_base.h b/engines/mm/mm1/views/character_base.h
index 008f2093198..44e7bac42c5 100644
--- a/engines/mm/mm1/views/character_base.h
+++ b/engines/mm/mm1/views/character_base.h
@@ -48,6 +48,7 @@ public:
CharacterBase(const Common::String &name) : TextView(name) {}
~CharacterBase() {}
+ bool msgKeypress(const KeypressMessage &msg) override;
void draw() override;
};
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
new file mode 100644
index 00000000000..91f5d952189
--- /dev/null
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -0,0 +1,122 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/character_info.h"
+#include "mm/mm1/utils/strings.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void CharacterInfo::draw() {
+ assert(g_globals->_currCharacter);
+ CharacterBase::draw();
+
+ switch (_state) {
+ case DISPLAY:
+ writeString(0, 21, STRING["dialogs.character.legend1"]);
+ writeString(0, 22, STRING["dialogs.character.legend2"]);
+ writeString(0, 23, STRING["dialogs.character.legend3"]);
+ writeString(0, 24, STRING["dialogs.character.legend4"]);
+ break;
+
+ case RENAME:
+ break;
+
+ case DELETE:
+ break;
+ }
+}
+
+bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ if (_state != DISPLAY) {
+ redraw();
+ } else {
+ close();
+ }
+
+ _state = DISPLAY;
+ return true;
+ }
+
+ switch (_state) {
+ case DISPLAY:
+ if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_n) {
+ _state = RENAME;
+ _newName = "";
+ redraw();
+ } else if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_d) {
+ _state = DELETE;
+ redraw();
+ }
+ break;
+
+ case RENAME:
+ if (msg.ascii >= 32 && msg.ascii <= 127) {
+ _newName += toupper(msg.ascii);
+ redraw();
+ }
+ if (msg.keycode == Common::KEYCODE_RETURN || _newName.size() == 15) {
+ strncpy(g_globals->_currCharacter->_name, _newName.c_str(), 16);
+ _state = DISPLAY;
+ redraw();
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
+ !_newName.empty()) {
+ _newName.deleteLastChar();
+ redraw();
+ }
+ break;
+
+ case DELETE:
+ if (msg.keycode == Common::KEYCODE_y) {
+ // Removes the character and returns to View All Characters
+ g_globals->_roster.remove(g_globals->_currCharacter);
+ close();
+ } else {
+ // Any other keypress returns to display mode
+ redraw();
+ }
+
+ _state = DISPLAY;
+ break;
+ }
+
+ return true;
+}
+
+bool CharacterInfo::msgAction(const ActionMessage &msg) {
+ if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6 &&
+ _state == DISPLAY) {
+ g_globals->_currCharacter = &g_globals->_party[
+ msg._action - KEYBIND_VIEW_PARTY1];
+ addView();
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
new file mode 100644
index 00000000000..97ee793dde4
--- /dev/null
+++ b/engines/mm/mm1/views/character_info.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_CHARACTER_INFO_H
+#define MM1_VIEWS_CHARACTER_INFO_H
+
+#include "common/array.h"
+#include "mm/mm1/views/character_base.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+/**
+ * In-game character dialog
+ */
+class CharacterInfo : public CharacterBase {
+ enum ViewState { DISPLAY = 0, RENAME = 1, DELETE = 2 };
+ ViewState _state = DISPLAY;
+ Common::String _newName;
+public:
+ CharacterInfo() : CharacterBase("CharacterInfo") {}
+ virtual ~CharacterInfo() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
+};
+
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/character_view.h b/engines/mm/mm1/views/character_view.h
new file mode 100644
index 00000000000..035b272e440
--- /dev/null
+++ b/engines/mm/mm1/views/character_view.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_CHARACTER_VIEW_H
+#define MM1_VIEWS_CHARACTER_VIEW_H
+
+#include "common/array.h"
+#include "mm/mm1/views/character_base.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+/**
+ * Character management dialog
+ */
+class CharacterView : public CharacterBase {
+public:
+ CharacterView() : CharacterBase("CharacterView") {}
+ virtual ~CharacterView() {}
+
+ void draw() {
+ CharacterBase::draw();
+ escToGoBack();
+ }
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/characters.cpp b/engines/mm/mm1/views/characters.cpp
index 0190de61d38..1ae9dd3fe7c 100644
--- a/engines/mm/mm1/views/characters.cpp
+++ b/engines/mm/mm1/views/characters.cpp
@@ -80,7 +80,7 @@ bool Characters::msgKeypress(const KeypressMessage &msg) {
// Character selected
uint charIndex = _charIndexes[msg.keycode - Common::KEYCODE_a];
g_globals->_currCharacter = &g_globals->_roster[charIndex];
- addView("ViewCharacter");
+ _characterView.addView();
}
return false;
diff --git a/engines/mm/mm1/views/characters.h b/engines/mm/mm1/views/characters.h
index ea274a26095..637af201acd 100644
--- a/engines/mm/mm1/views/characters.h
+++ b/engines/mm/mm1/views/characters.h
@@ -24,6 +24,7 @@
#include "common/array.h"
#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/character_manage.h"
namespace MM {
namespace MM1 {
@@ -35,6 +36,7 @@ namespace Views {
class Characters : public TextView {
private:
Common::Array<uint> _charIndexes;
+ CharacterManage _characterView;
public:
Characters() : TextView("Characters") {}
virtual ~Characters() {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 529943b13d3..1cd578248e4 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -31,7 +31,7 @@
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
-#include "mm/mm1/views/character_manage.h"
+#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
@@ -55,8 +55,7 @@ private:
Views::Protect _protect;
Views::QuickRef _quickRef;
Views::Title _title;
-// Views::ViewCharacters _viewCharacters;
- Views::CharacterManage _characterManage;
+ Views::CharacterInfo _characterInfo;
Views::Locations::Blacksmith _blacksmith;
Views::Locations::Inn _inn;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index ee9ef1777d1..135b9bf9eee 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -50,11 +50,28 @@ void Game::draw() {
bool Game::msgAction(const ActionMessage &msg) {
switch (msg._action) {
case KEYBIND_ORDER:
- g_events->send("Game", GameMessage("ORDER"));
+// g_events->send("Game", GameMessage("ORDER"));
+ addView("Order");
+ return true;
+ case KEYBIND_QUICKREF:
+ addView("QuickRef");
return true;
case KEYBIND_SEARCH:
MM1::Game::Search::execute();
break;
+ case KEYBIND_VIEW_PARTY1:
+ case KEYBIND_VIEW_PARTY2:
+ case KEYBIND_VIEW_PARTY3:
+ case KEYBIND_VIEW_PARTY4:
+ case KEYBIND_VIEW_PARTY5:
+ case KEYBIND_VIEW_PARTY6: {
+ uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
+ if (charNum < g_globals->_party.size()) {
+ g_globals->_currCharacter = &g_globals->_party[charNum];
+ addView("CharacterInfo");
+ }
+ break;
+ }
default:
break;
}
diff --git a/engines/mm/mm1/views/locations/inn.cpp b/engines/mm/mm1/views/locations/inn.cpp
index fcf271b5b27..9218defcd26 100644
--- a/engines/mm/mm1/views/locations/inn.cpp
+++ b/engines/mm/mm1/views/locations/inn.cpp
@@ -117,7 +117,7 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
} else if (msg.flags == 0) {
// View character
g_globals->_currCharacter = &g_globals->_roster[charNum];
- addView("ViewCharacter");
+ _characterView.addView();
}
} else if (msg.keycode == Common::KEYCODE_x) {
// Load party from selected characters
diff --git a/engines/mm/mm1/views/locations/inn.h b/engines/mm/mm1/views/locations/inn.h
index 6a054521f79..bb2c3a32763 100644
--- a/engines/mm/mm1/views/locations/inn.h
+++ b/engines/mm/mm1/views/locations/inn.h
@@ -23,6 +23,7 @@
#define MM1_VIEWS_LOCATIONS_INN_H
#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/character_view.h"
#include "mm/mm1/data/int_array.h"
namespace MM {
@@ -32,6 +33,7 @@ namespace Locations {
class Inn : public TextView {
private:
+ CharacterView _characterView;
Common::Array<uint> _charNums;
IntArray _partyChars;
public:
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 29d779450b2..25729ada36a 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -91,9 +91,19 @@ bool QuickRef::msgKeypress(const KeypressMessage &msg) {
bool QuickRef::msgAction(const ActionMessage &msg) {
switch (msg._action) {
- case KEYBIND_QUICKREF:
- addView();
- return true;
+ case KEYBIND_VIEW_PARTY1:
+ case KEYBIND_VIEW_PARTY2:
+ case KEYBIND_VIEW_PARTY3:
+ case KEYBIND_VIEW_PARTY4:
+ case KEYBIND_VIEW_PARTY5:
+ case KEYBIND_VIEW_PARTY6: {
+ uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
+ if (charNum < g_globals->_party.size()) {
+ g_globals->_currCharacter = &g_globals->_party[charNum];
+ replaceView("CharacterInfo");
+ }
+ break;
+ }
default:
break;
}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index cd682a4e886..c7e1b407be0 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -38,6 +38,7 @@ MODULE_OBJS := \
mm1/views/locations/training.o \
mm1/views/are_you_ready.o \
mm1/views/character_base.o \
+ mm1/views/character_info.o \
mm1/views/character_manage.o \
mm1/views/characters.o \
mm1/views/create_characters.o \
Commit: da1961795be587f4f263db5a6bf200b77bfacca6
https://github.com/scummvm/scummvm/commit/da1961795be587f4f263db5a6bf200b77bfacca6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:57+01:00
Commit Message:
MM: MM1: Implement gather gold in Character Info dialog
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/locations/location.cpp
engines/mm/mm1/views/locations/location.h
engines/mm/mm1/views/locations/tavern.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/locations/training.cpp
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 76cb4ed3038..5650a63a8c3 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -108,6 +108,17 @@ void Character::clear() {
_v66 = _v67 = _v6c = _v6f = 0;
}
+
+void Character::gatherGold() {
+ uint total = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ total += g_globals->_party[i]._gold;
+ g_globals->_party[i]._gold = 0;
+ }
+
+ _gold = total;
+}
+
Character::LevelIncrease Character::increaseLevel() {
_level = ++_levelBase;
_age = ++_ageBase;
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 486d8feb5a8..e05daf2b965 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -110,6 +110,11 @@ struct Character {
*/
void clear();
+ /**
+ * Gathers the party gold into the character
+ */
+ void gatherGold();
+
/**
* Increase the character's level by 1 at a trainer
*/
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 91f5d952189..db2b03f8f1d 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -61,42 +61,23 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
switch (_state) {
case DISPLAY:
- if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_n) {
- _state = RENAME;
- _newName = "";
+ switch (msg.keycode) {
+ case Common::KEYCODE_g:
+ g_globals->_currCharacter->gatherGold();
redraw();
- } else if ((msg.flags & Common::KBD_CTRL) && msg.keycode == Common::KEYCODE_d) {
- _state = DELETE;
- redraw();
- }
+ break;
+ case Common::KEYCODE_q:
+ replaceView("QuickRef");
+ break;
+ default:
+ break;
+ }
break;
case RENAME:
- if (msg.ascii >= 32 && msg.ascii <= 127) {
- _newName += toupper(msg.ascii);
- redraw();
- }
- if (msg.keycode == Common::KEYCODE_RETURN || _newName.size() == 15) {
- strncpy(g_globals->_currCharacter->_name, _newName.c_str(), 16);
- _state = DISPLAY;
- redraw();
- } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
- !_newName.empty()) {
- _newName.deleteLastChar();
- redraw();
- }
break;
case DELETE:
- if (msg.keycode == Common::KEYCODE_y) {
- // Removes the character and returns to View All Characters
- g_globals->_roster.remove(g_globals->_currCharacter);
- close();
- } else {
- // Any other keypress returns to display mode
- redraw();
- }
-
_state = DISPLAY;
break;
}
diff --git a/engines/mm/mm1/views/locations/location.cpp b/engines/mm/mm1/views/locations/location.cpp
index 46a21c2b62d..1701cdb0b1a 100644
--- a/engines/mm/mm1/views/locations/location.cpp
+++ b/engines/mm/mm1/views/locations/location.cpp
@@ -60,16 +60,6 @@ void Location::newLine() {
_textPos.y = 0;
}
-void Location::gatherGold() {
- uint total = 0;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- total += g_globals->_party[i]._gold;
- g_globals->_party[i]._gold = 0;
- }
-
- g_globals->_currCharacter->_gold = total;
-}
-
bool Location::subtractGold(uint amount) {
if (g_globals->_currCharacter->_gold < amount) {
notEnoughGold();
diff --git a/engines/mm/mm1/views/locations/location.h b/engines/mm/mm1/views/locations/location.h
index 4c135570c5f..0c96be8783b 100644
--- a/engines/mm/mm1/views/locations/location.h
+++ b/engines/mm/mm1/views/locations/location.h
@@ -54,11 +54,6 @@ protected:
*/
void leave();
- /**
- * Gathers all the party gold to the current character
- */
- void gatherGold();
-
/**
* Subtract gold from current character
*/
diff --git a/engines/mm/mm1/views/locations/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
index c8d4b065bcb..2971d9cf9a1 100644
--- a/engines/mm/mm1/views/locations/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -54,7 +54,7 @@ bool Tavern::msgKeypress(const KeypressMessage &msg) {
listenForRumors();
break;
case Common::KEYCODE_g:
- gatherGold();
+ g_globals->_currCharacter->gatherGold();
redraw();
break;
case Common::KEYCODE_1:
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index e30cdcb68b9..8b30037e6fd 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -58,7 +58,7 @@ bool Temple::msgKeypress(const KeypressMessage &msg) {
donate();
break;
case Common::KEYCODE_g:
- gatherGold();
+ g_globals->_currCharacter->gatherGold();
redraw();
break;
case Common::KEYCODE_1:
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index 523f4e0c93c..19b512c891e 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -126,7 +126,7 @@ bool Training::msgKeypress(const KeypressMessage &msg) {
train();
break;
case Common::KEYCODE_g:
- gatherGold();
+ g_globals->_currCharacter->gatherGold();
redraw();
break;
case Common::KEYCODE_1:
Commit: e4b88b84ff82bdde0d0ebb545bf7998512c1b241
https://github.com/scummvm/scummvm/commit/e4b88b84ff82bdde0d0ebb545bf7998512c1b241
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:57+01:00
Commit Message:
MM: MM1: Implemented Inventory class for backpack & equipped
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 5650a63a8c3..f68fa575b19 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -30,6 +30,30 @@ static const int CLASS_HP_PER_LEVEL[6] = {
12, 10, 10, 8, 6, 8
};
+void Inventory::clear() {
+ Common::fill(_items, _items + INVENTORY_COUNT, 0);
+}
+
+void Inventory::synchronize(Common::Serializer &s) {
+ s.syncBytes(_items, INVENTORY_COUNT);
+}
+
+bool Inventory::empty() const {
+ for (uint i = 0; i < INVENTORY_COUNT; ++i) {
+ if (_items[i])
+ return false;
+ }
+ return true;
+}
+
+bool Inventory::full() const {
+ for (uint i = 0; i < INVENTORY_COUNT; ++i) {
+ if (!_items[i])
+ return false;
+ }
+ return true;
+}
+
void Character::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
s.syncAsByte(_sex);
@@ -72,8 +96,8 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_food);
s.syncAsByte(_condition);
- s.syncBytes(_equipped, INVENTORY_COUNT);
- s.syncBytes(_backpack, INVENTORY_COUNT);
+ _equipped.synchronize(s);
+ _backpack.synchronize(s);
// TODO: Figure purpose of remaining unknown fields
s.skip(51);
@@ -99,8 +123,9 @@ void Character::clear() {
_ac = 0;
_food = 0;
_condition = 0;
- Common::fill(_equipped, _equipped + INVENTORY_COUNT, 0);
- Common::fill(_backpack, _backpack + INVENTORY_COUNT, 0);
+ _equipped.clear();
+ _backpack.clear();
+ _backpack14.clear();
_alignmentInitial = GOOD;
_alignment = GOOD;
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index e05daf2b965..dfa817ce63c 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -54,6 +54,28 @@ enum Condition {
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
};
+class Inventory {
+private:
+ byte _items[INVENTORY_COUNT];
+public:
+ Inventory() {
+ clear();
+ }
+ byte &operator[](uint idx) {
+ assert(idx < INVENTORY_COUNT);
+ return _items[idx];
+ }
+ const byte &operator[](uint idx) const {
+ assert(idx < INVENTORY_COUNT);
+ return _items[idx];
+ }
+
+ void synchronize(Common::Serializer &s);
+ void clear();
+ bool empty() const;
+ bool full() const;
+};
+
struct Character {
char _name[16] = { 0 };
Sex _sex = MALE;
@@ -81,10 +103,9 @@ struct Character {
byte _ac = 0;
uint8 _food = 0;
uint8 _condition = 0;
- uint8 _equipped[INVENTORY_COUNT] = { 0 };
- uint8 _backpack[INVENTORY_COUNT] = { 0 };
-
- uint8 _backpack14[INVENTORY_COUNT] = { 0 };
+ Inventory _equipped;
+ Inventory _backpack;
+ Inventory _backpack14;
// TODO: Figure out what these are
int _v58, _v59, _v62, _v63, _v64, _v65;
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index db2b03f8f1d..2b0464a1fd2 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -39,10 +39,10 @@ void CharacterInfo::draw() {
writeString(0, 24, STRING["dialogs.character.legend4"]);
break;
- case RENAME:
+ case EQUIP:
break;
- case DELETE:
+ case REMOVE:
break;
}
}
@@ -62,6 +62,10 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
switch (_state) {
case DISPLAY:
switch (msg.keycode) {
+ case Common::KEYCODE_e:
+ if (!g_globals->_currCharacter->_backpack.empty())
+ _state = EQUIP;
+ break;
case Common::KEYCODE_g:
g_globals->_currCharacter->gatherGold();
redraw();
@@ -69,16 +73,22 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_q:
replaceView("QuickRef");
break;
+ case Common::KEYCODE_r:
+ if (!g_globals->_currCharacter->_equipped.empty())
+ _state = REMOVE;
+ break;
default:
break;
}
break;
- case RENAME:
+ case EQUIP:
break;
- case DELETE:
- _state = DISPLAY;
+ case REMOVE:
+ break;
+
+ default:
break;
}
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 97ee793dde4..e0b979b2145 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -33,7 +33,7 @@ namespace Views {
* In-game character dialog
*/
class CharacterInfo : public CharacterBase {
- enum ViewState { DISPLAY = 0, RENAME = 1, DELETE = 2 };
+ enum ViewState { DISPLAY = 0, EQUIP = 1, REMOVE = 2 };
ViewState _state = DISPLAY;
Common::String _newName;
public:
Commit: b4ee049bd20f9670cd632687b348124ff9ba32de
https://github.com/scummvm/scummvm/commit/b4ee049bd20f9670cd632687b348124ff9ba32de
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:57+01:00
Commit Message:
MM: MM1: Most of the character info equip item
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/data/items.cpp
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
engines/mm/mm1/views/locations/blacksmith_subview.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index fe99cfd6933..6c1bcdc4913 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -25,6 +25,18 @@ dialogs:
legend2: " # VIEW OTHER 'D' DISCARD 'S' SHARE"
legend3: " 'E' EQUIP 'T' TRADE"
legend4: "'ESC' TO GO BACK 'G' GATHER 'U' USE"
+ equip: "EQUIP WHICH ITEM: 'A'-'F'?"
+ remove: "REMOVE WHICH ITEM: '1'-'6'?"
+ wrong_class: "*** WRONG CLASS ***"
+ have_armor: "*** ALREADY WEARING ARMOR ***"
+ not_equipped: "*** NOT EQUIPPED ***"
+ cannot_with_shield: "*** CANNOT WITH SHIELD ***"
+ already_have_one: "*** ALREADY HAVE ONE ***"
+ cannot_two_handed: "*** CANNOT WITH TWO-HANDED WEAPON ***"
+ have_weapon: "*** ALREADY HAVE WEAPON ***"
+ full: "*** FULL ***"
+ have_missile: "*** AREADY HAVE MISSILE WEAPON ***"
+ wrong_alignment: "*** WRONG ALIGNMENT ***"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index f68fa575b19..950618ce6bf 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -31,11 +31,12 @@ static const int CLASS_HP_PER_LEVEL[6] = {
};
void Inventory::clear() {
- Common::fill(_items, _items + INVENTORY_COUNT, 0);
+ _items.clear();
+ _items.resize(INVENTORY_COUNT);
}
void Inventory::synchronize(Common::Serializer &s) {
- s.syncBytes(_items, INVENTORY_COUNT);
+ s.syncBytes(&_items[0], INVENTORY_COUNT);
}
bool Inventory::empty() const {
@@ -54,6 +55,32 @@ bool Inventory::full() const {
return true;
}
+int Inventory::getFreeSlot() const {
+ for (uint i = 0; i < INVENTORY_COUNT; ++i) {
+ if (!_items[i])
+ return i;
+ }
+
+ error("Inventory is full");
+ return -1;
+}
+
+
+void Inventory::removeAt(uint idx) {
+ _items.remove_at(idx);
+ _items.push_back(0);
+}
+
+bool Inventory::hasCategory(CategoryFn fn) const {
+ for (uint i = 0; i < INVENTORY_COUNT; ++i) {
+ if (fn(_items[i]))
+ return true;
+ }
+ return false;
+}
+
+/*------------------------------------------------------------------------*/
+
void Character::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
s.syncAsByte(_sex);
@@ -98,9 +125,11 @@ void Character::synchronize(Common::Serializer &s) {
_equipped.synchronize(s);
_backpack.synchronize(s);
+ _equipped14.synchronize(s);
+ _backpack14.synchronize(s);
// TODO: Figure purpose of remaining unknown fields
- s.skip(51);
+ s.skip(39);
}
void Character::clear() {
@@ -237,7 +266,7 @@ Character::BuyResult Character::buyItem(byte itemId) {
// Add the item
_gold -= item._cost;
_backpack[slotIndex] = itemId;
- _backpack14[slotIndex] = item._field14;
+ _backpack14[slotIndex] = item._val13;
return BUY_SUCCESS;
}
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index dfa817ce63c..6e18a9f799f 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -22,7 +22,9 @@
#ifndef MM1_DATA_CHAR_H
#define MM1_DATA_CHAR_H
+#include "common/array.h"
#include "common/serializer.h"
+#include "mm/mm1/data/items.h"
namespace MM {
namespace MM1 {
@@ -56,7 +58,13 @@ enum Condition {
class Inventory {
private:
- byte _items[INVENTORY_COUNT];
+ Common::Array<byte> _items;
+
+ /**
+ * Used to test if the inventory has a category of item
+ */
+ typedef bool (*CategoryFn)(byte id);
+ bool hasCategory(CategoryFn fn) const;
public:
Inventory() {
clear();
@@ -70,10 +78,45 @@ public:
return _items[idx];
}
+ /**
+ * Saves or loads the inventory data
+ */
void synchronize(Common::Serializer &s);
+
+ /**
+ * Clears the inventory
+ */
void clear();
+
+ /**
+ * Returns true if the inventory is empty
+ */
bool empty() const;
+
+ /**
+ * Returns true if the inventory is full
+ */
bool full() const;
+
+ /**
+ * Returns the index of a free slot
+ */
+ int getFreeSlot() const;
+
+ /**
+ * Removes an index from the inventory
+ */
+ void removeAt(uint idx);
+
+ /**
+ * The following methods return true if any of
+ * the contained items are of the given category
+ */
+ bool hasWeapon() const { return hasCategory(isWeapon); }
+ bool hasMissile() const { return hasCategory(isMissile); }
+ bool hasTwoHanded() const { return hasCategory(isTwoHanded); }
+ bool hasArmor() const { return hasCategory(isArmor); }
+ bool hasShield() const { return hasCategory(isShield); }
};
struct Character {
@@ -100,16 +143,19 @@ struct Character {
uint16 _gems = 0;
uint16 _hpBase = 0, _hp = 0, _hpMax = 0;
uint32 _gold = 0;
+ byte _v3c = 0;
byte _ac = 0;
uint8 _food = 0;
uint8 _condition = 0;
Inventory _equipped;
Inventory _backpack;
+ Inventory _equipped14;
Inventory _backpack14;
// TODO: Figure out what these are
int _v58, _v59, _v62, _v63, _v64, _v65;
- int _v66, _v67, _v6c, _v6e, _v6f;
+ int _v66, _v67, _v68, _v69, _v6a, _v6b,
+ _v6c, _v6e, _v6f;
// Non persistent fields
byte _numDrinks = 0;
diff --git a/engines/mm/mm1/data/items.cpp b/engines/mm/mm1/data/items.cpp
index 6e54815daa3..527dc591cf5 100644
--- a/engines/mm/mm1/data/items.cpp
+++ b/engines/mm/mm1/data/items.cpp
@@ -26,7 +26,7 @@ namespace MM {
namespace MM1 {
// TODO: Figure out all item fields
-const Item ITEMS1[86] = {
+const ItemData ITEMS1[86] = {
{ 0 },
{ 0 },
{ 0 },
@@ -115,7 +115,7 @@ const Item ITEMS1[86] = {
{ 0 }
};
-const Item ITEMS2[] = {
+const ItemData ITEMS2[] = {
{ 0 }
};
@@ -128,5 +128,20 @@ Item *getItem(byte index) {
return &g_globals->_currItem;
}
+ItemCategory getItemCategory(byte itemId) {
+ if (isWeapon(itemId))
+ return ITEMCAT_WEAPON;
+ if (isMissile(itemId))
+ return ITEMCAT_MISSILE;
+ if (isTwoHanded(itemId))
+ return ITEMCAT_TWO_HANDED;
+ if (isArmor(itemId))
+ return ITEMCAT_ARMOR;
+ if (isShield(itemId))
+ return ITEMCAT_SHIELD;
+
+ return ITEMCAT_NONE;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 615ad1d0715..e2c5a00f8c3 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -27,21 +27,67 @@
namespace MM {
namespace MM1 {
-struct Item {
- Common::String _name;
- byte _enablement;
- byte _field10;
- byte _field11;
- byte _field14;
+enum EnablementBit {
+ KNIGHT_BIT = 0x20, PALADIN_BIT = 0x10, ARCHER_BIT = 8,
+ CLERIC_BIT = 4, SORCERER_BIT = 2, ROBBER_BIT = 1,
+ GOOD_BIT = 0x80, EVIL_BIT = 0x40,
+ NEUTRAL_BIT = GOOD_BIT | EVIL_BIT
+};
+
+enum ItemCategory {
+ ITEMCAT_NONE, ITEMCAT_WEAPON, ITEMCAT_MISSILE,
+ ITEMCAT_TWO_HANDED, ITEMCAT_ARMOR, ITEMCAT_SHIELD
+};
+
+enum EquipMode {
+ EQUIPMODE_0 = 0, NOT_EQUIPPABLE = 1,
+ EQUIP_CURSED = 0xff
+};
+
+struct ItemData {
+ byte _disablements;
+ EquipMode _equipMode;
+ byte _val10;
+ byte _val11;
+ byte _val12;
+ byte _val13;
uint16 _cost;
- byte _field17;
- byte _field18;
+ byte _val16;
+ byte _val17;
+};
+
+struct Item : public ItemData {
+ Common::String _name;
+
+ Item *operator=(const ItemData &rhs) {
+ *dynamic_cast<ItemData *>(this) = rhs;
+ _name.clear();
+ return this;
+ }
};
-extern const Item ITEMS1[];
-extern const Item ITEMS2[];
+extern const ItemData ITEMS1[];
+extern const ItemData ITEMS2[];
+
+
+inline bool isWeapon(byte id) {
+ return id >= 1 && id <= 60;
+};
+inline bool isMissile(byte id) {
+ return id >= 61 && id <= 85;
+};
+inline bool isTwoHanded(byte id) {
+ return id >= 86 && id <= 120;
+};
+inline bool isArmor(byte id) {
+ return id >= 121 && id <= 155;
+};
+inline bool isShield(byte id) {
+ return id >= 156 && id <= 170;
+};
extern Item *getItem(byte index);
+extern ItemCategory getItemCategory(byte itemId);
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index d78c5d4f077..473338d96d3 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -33,7 +33,7 @@ Map::Map(uint index, const Common::String &name, uint16 id) :
_mapIndex(index), _name(name), _id(id) {
Common::fill((byte *)&_walls[0], (byte *)&_walls[MAP_SIZE], 0);
Common::fill(&_states[0], (byte *)&_states[MAP_SIZE], 0);
- Common::fill(&_visited[0], &_visited[MAP_SIZE], false);
+ Common::fill(&_visited[0], &_visited[MAP_SIZE], 0);
}
void Map::load() {
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 2b0464a1fd2..1f51ca9ec26 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -40,9 +40,13 @@ void CharacterInfo::draw() {
break;
case EQUIP:
+ writeString(0, 20, STRING["dialogs.chracter.equip"]);
+ escToGoBack(0);
break;
case REMOVE:
+ writeString(0, 20, STRING["dialogs.chracter.remove"]);
+ escToGoBack(0);
break;
}
}
@@ -83,6 +87,9 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
break;
case EQUIP:
+ if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode <= Common::KEYCODE_f)
+ equipItem(msg.keycode - Common::KEYCODE_a);
break;
case REMOVE:
@@ -108,6 +115,166 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
return false;
}
+void CharacterInfo::equipItem(uint index) {
+ Character &c = *g_globals->_currCharacter;
+ uint itemId = c._backpack[index];
+ uint item14 = c._backpack14[index];
+
+ int classBit = 0;
+ Common::String equipError;
+ _textPos.x = 0;
+
+ switch (c._class) {
+ case KNIGHT:
+ classBit = KNIGHT_BIT;
+ break;
+ case PALADIN:
+ classBit = PALADIN_BIT;
+ break;
+ case ARCHER:
+ classBit = ARCHER_BIT;
+ break;
+ case CLERIC:
+ classBit = CLERIC_BIT;
+ break;
+ case SORCERER:
+ classBit = SORCERER_BIT;
+ break;
+ case ROBBER:
+ classBit = ROBBER_BIT;
+ break;
+ default:
+ equipError = STRING["dialogs.character.wrong_class"];
+ break;
+ }
+
+ getItem(itemId);
+ const Item &item = g_globals->_currItem;
+
+ if (equipError.empty() && (item._disablements & classBit))
+ equipError = STRING["dialogs.character.wrong_class"];
+ if (equipError.empty()) {
+ int alignBit = 0;
+ switch (c._alignment) {
+ case GOOD:
+ alignBit = GOOD_BIT;
+ break;
+ case NEUTRAL:
+ alignBit = NEUTRAL_BIT;
+ break;
+ case EVIL:
+ alignBit = EVIL_BIT;
+ break;
+ default:
+ equipError = STRING["dialogs.character.wrong_alignment"];
+ break;
+ }
+
+ if ((item._disablements & alignBit) && alignBit != NEUTRAL_BIT)
+ equipError = STRING["dialogs.character.wrong_alignment"];
+ }
+
+ if (equipError.empty()) {
+ if (item._equipMode == NOT_EQUIPPABLE) {
+ equipError = STRING["dialogs.character.not_equipped"];
+ _textPos.x = 10;
+ }
+ }
+
+ if (equipError.empty()) {
+ if (isWeapon(itemId)) {
+ if (c._equipped.hasWeapon() || c._equipped.hasTwoHanded())
+ equipError = STRING["dialogs.character.have_weapon"];
+ } else if (isMissile(itemId)) {
+ if (c._equipped.hasMissile()) {
+ equipError = STRING["dialogs.character.have_missile"];
+ _textPos.x = 3;
+ }
+ } else if (isTwoHanded(itemId)) {
+ if (c._equipped.hasShield()) {
+ equipError = STRING["dialogs.character.cannot_with_shield"];
+ _textPos.x = 7;
+ } else if (c._equipped.hasWeapon()) {
+ equipError = STRING["dialogs.character.have_weapon"];
+
+ }
+ } else if (isArmor(itemId)) {
+ if (c._equipped.hasArmor()) {
+ equipError = STRING["dialogs.character.have_armor"];
+ _textPos.x = 5;
+ }
+ } else if (isShield(itemId)) {
+ if (c._equipped.hasTwoHanded()) {
+ equipError = STRING["dialogs.character.cannot_two_handed"];
+ _textPos.x = 1;
+ }
+ } else if (itemId == 255) {
+ equipError = STRING["dialogs.character.not_equipped"];
+ _textPos.x = 10;
+ }
+ }
+
+ if (equipError.empty() && c._equipped.full()) {
+ equipError = STRING["dialogs.character.full"];
+ _textPos.x = 14;
+ }
+
+ if (equipError.empty()) {
+ // All checks passed, can equip item
+ c._backpack.removeAt(index);
+ c._backpack14.removeAt(index);
+
+ int freeIndex = c._equipped.getFreeSlot();
+ c._equipped[freeIndex] = itemId;
+ c._equipped14[freeIndex] = item14;
+
+ if (item._equipMode != EQUIPMODE_0) {
+ if (item._equipMode == NOT_EQUIPPABLE) {
+ equipError = STRING["dialogs.character.not_equipped"];
+ _textPos.x = 10;
+ } else if (item._equipMode == EQUIP_CURSED) {
+ c._equipped14[freeIndex] += item._val10;
+ }
+ }
+ }
+
+ if (equipError.empty()) {
+ switch (getItemCategory(itemId)) {
+ case ITEMCAT_WEAPON:
+ case ITEMCAT_TWO_HANDED:
+ c._v68 = item._val16;
+ c._v69 = item._val17;
+ break;
+ case ITEMCAT_MISSILE:
+ c._v6a = item._val16;
+ c._v6b = item._val17;
+ break;
+ c._v68 = item._val16;
+ c._v69 = item._val17;
+ break;
+ case ITEMCAT_ARMOR:
+ case ITEMCAT_SHIELD:
+ c._v3c += item._val17;
+ break;
+ default:
+ break;
+ }
+
+ // TODO: Stuff
+ } else {
+ clearLines(20, 24);
+ _textPos.y = 21;
+ writeString(equipError);
+
+ _state = DISPLAY;
+ // TODO: Delay
+ }
+}
+
+void CharacterInfo::removeItem(uint index) {
+
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index e0b979b2145..59b397022c7 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -33,9 +33,20 @@ namespace Views {
* In-game character dialog
*/
class CharacterInfo : public CharacterBase {
+private:
enum ViewState { DISPLAY = 0, EQUIP = 1, REMOVE = 2 };
ViewState _state = DISPLAY;
Common::String _newName;
+private:
+ /**
+ * Equips the item at the given index
+ */
+ void equipItem(uint index);
+
+ /**
+ * Removes the equipped item at the given index
+ */
+ void removeItem(uint index);
public:
CharacterInfo() : CharacterBase("CharacterInfo") {}
virtual ~CharacterInfo() {}
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index 454ea6605fe..ca98d221527 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -71,7 +71,7 @@ void BlacksmithSellItem::selectItem(uint index) {
c._backpack14[index] = 0;
getItem(itemId);
- if (!v14 && g_globals->_currItem._field14)
+ if (!v14 && g_globals->_currItem._val13)
g_globals->_currItem._cost /= 2;
c._gold += g_globals->_currItem._cost / 2;
diff --git a/engines/mm/mm1/views/locations/blacksmith_subview.cpp b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
index 0005f4b91d8..2186cb6c87a 100644
--- a/engines/mm/mm1/views/locations/blacksmith_subview.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
@@ -48,7 +48,7 @@ void BlacksmithSubview::drawIsAllowed() {
if (c._class != NONE && c._class <= ROBBER) {
if (!(BLACKSMITH_CLASS_USAGE[c._class - 1] &
- g_globals->_currItem._enablement))
+ g_globals->_currItem._disablements))
return;
}
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 8b30037e6fd..f495ee62717 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -106,7 +106,7 @@ void Temple::changeCharacter(uint index) {
_uncurseCost = UNCURSE_COST[townNum];
for (i = 0; i < INVENTORY_COUNT; ++i) {
if (c._equipped[i]) {
- if (getItem(c._equipped[i])->_field10 == 0xff)
+ if (getItem(c._equipped[i])->_equipMode == EQUIP_CURSED)
break;
}
}
@@ -173,8 +173,10 @@ void Temple::uncurseItems() {
for (int i = 0; i < INVENTORY_COUNT; ++i) {
if (c._equipped[i]) {
getItem(c._equipped[i]);
- if (g_globals->_currItem._field10 == 0xff)
- c._equipped[i] = 0;
+ if (g_globals->_currItem._equipMode == EQUIP_CURSED) {
+ c._equipped.removeAt(i);
+ --i;
+ }
}
}
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index b9e56942e6f..8034511f8b3 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -123,8 +123,8 @@ void TextView::drawTextBorder() {
}
}
-void TextView::escToGoBack() {
- writeString(12, 24, STRING["dialogs.misc.go_back"]);
+void TextView::escToGoBack(int x) {
+ writeString(x, 24, STRING["dialogs.misc.go_back"]);
}
} // namespace Views
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 5d1be1660c4..58d5f0821c7 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -77,7 +77,7 @@ protected:
/**
* Prints a message 'ESC' to go back
*/
- void escToGoBack();
+ void escToGoBack(int x = 12);
public:
TextView(const Common::String &name);
TextView(const Common::String &name, UIElement *owner);
Commit: 3bbe7c32d48f5951f8acca1a4677a355b73365ef
https://github.com/scummvm/scummvm/commit/3bbe7c32d48f5951f8acca1a4677a355b73365ef
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Remainder of equip item
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/character_base.cpp
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/locations/location.cpp
engines/mm/mm1/views/locations/location.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 950618ce6bf..57cb00e9d64 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -111,8 +111,8 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsUint32LE(_exp);
s.syncAsUint16LE(_sp);
s.syncAsUint16LE(_spMax);
- s.syncAsByte(_sp2);
- s.syncAsByte(_maxSpellLevel);
+ s.syncAsByte(_slvlBase);
+ s.syncAsByte(_slvl);
s.syncAsUint16LE(_gems);
s.syncAsUint16LE(_hpBase);
s.syncAsUint16LE(_hp);
@@ -145,7 +145,7 @@ void Character::clear() {
_age = 0;
_exp = 0;
_sp = _spMax = 0;
- _maxSpellLevel = _sp2 = 0;
+ _slvl = _slvlBase = 0;
_gems = 0;
_hpBase = _hp = _hpMax = 0;
_gold = 0;
@@ -271,5 +271,50 @@ Character::BuyResult Character::buyItem(byte itemId) {
return BUY_SUCCESS;
}
+void Character::updateAttributes() {
+ _int = _intBase;
+ _mgt = _mgtBase;
+ _per = _perBase;
+ _end = _endBase;
+ _spd = _spdBase;
+ _acy = _acyBase;
+ _luc = _lucBase;
+ _level = _levelBase;
+ _slvl = _slvlBase;
+}
+
+void Character::updateAC() {
+ int ac = _acBase;
+
+ if (_spd >= 40)
+ ac += 9;
+ else if (_spd >= 35)
+ ac += 8;
+ else if (_spd >= 30)
+ ac += 7;
+ else if (_spd >= 25)
+ ac += 6;
+ else if (_spd >= 21)
+ ac += 5;
+ else if (_spd >= 19)
+ ac += 4;
+ else if (_spd >= 17)
+ ac += 3;
+ else if (_spd >= 15)
+ ac += 2;
+ else if (_spd >= 13)
+ ac += 1;
+ else if (_spd >= 9)
+ ac += 0;
+ else if (_spd >= 7)
+ ac = MAX(ac - 1, 0);
+ else if (_spd >= 5)
+ ac = MAX(ac - 2, 0);
+ else
+ ac = MAX(ac - 3, 0);
+
+ _ac = ac;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 6e18a9f799f..d9bdd540646 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -139,12 +139,12 @@ struct Character {
uint8 _age = 0;
uint32 _exp = 0;
uint16 _sp = 0, _spMax = 0;
- uint8 _sp2 = 0, _maxSpellLevel = 0;
+ uint8 _slvlBase = 0, _slvl = 0;
+
uint16 _gems = 0;
uint16 _hpBase = 0, _hp = 0, _hpMax = 0;
uint32 _gold = 0;
- byte _v3c = 0;
- byte _ac = 0;
+ byte _acBase = 0, _ac = 0;
uint8 _food = 0;
uint8 _condition = 0;
Inventory _equipped;
@@ -196,6 +196,17 @@ struct Character {
*/
enum BuyResult { BUY_SUCCESS, BUY_NOT_ENOUGH_GOLD, BUY_BACKPACK_FULL };
BuyResult buyItem(byte itemId);
+
+ /**
+ * Updates the current attribute levels to match
+ * their base values
+ */
+ void updateAttributes();
+
+ /**
+ * Updates the character's AC
+ */
+ void updateAC();
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/character_base.cpp b/engines/mm/mm1/views/character_base.cpp
index 9e05b98f26f..a109fdb9bea 100644
--- a/engines/mm/mm1/views/character_base.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -59,7 +59,7 @@ void CharacterBase::printStats() {
writeNumber(re._spMax);
_textPos.x = 22;
writeChar('(');
- writeNumber(re._maxSpellLevel);
+ writeNumber(re._slvl);
writeChar(')');
_textPos.x = 26;
writeString(STRING["stats.attributes.gems"]);
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 1f51ca9ec26..161eb092977 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -22,6 +22,7 @@
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/utils/strings.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -254,21 +255,26 @@ void CharacterInfo::equipItem(uint index) {
break;
case ITEMCAT_ARMOR:
case ITEMCAT_SHIELD:
- c._v3c += item._val17;
+ c._acBase += item._val17;
break;
default:
break;
}
- // TODO: Stuff
+ warning("TODO: c field58");
+ c.updateAttributes();
+ c.updateAC();
+
} else {
clearLines(20, 24);
_textPos.y = 21;
writeString(equipError);
- _state = DISPLAY;
- // TODO: Delay
+ Sound::sound(SOUND_2);
+ delaySeconds(5);
}
+
+ _state = DISPLAY;
}
void CharacterInfo::removeItem(uint index) {
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index f81af480acf..d525cf1ae53 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -176,7 +176,7 @@ void CreateCharacters::NewCharacter::setSP(int amount) {
level = 1;
re._sp = re._spMax = level + 3;
- re._maxSpellLevel = re._sp2 = 1;
+ re._slvl = re._slvlBase = 1;
}
/*------------------------------------------------------------------------*/
diff --git a/engines/mm/mm1/views/locations/location.cpp b/engines/mm/mm1/views/locations/location.cpp
index 1701cdb0b1a..2b79495dd1d 100644
--- a/engines/mm/mm1/views/locations/location.cpp
+++ b/engines/mm/mm1/views/locations/location.cpp
@@ -80,10 +80,6 @@ void Location::backpackFull() {
displayMessage(STRING["dialogs.misc.backpack_full"]);
}
-void Location::delaySeconds(uint seconds) {
- _timeoutCtr = seconds * FRAME_RATE;
-}
-
void Location::changeCharacter(uint index) {
if (index >= g_globals->_party.size())
return;
@@ -98,18 +94,6 @@ void Location::leave() {
g_events->redraw();
}
-bool Location::tick() {
- if (_timeoutCtr && --_timeoutCtr == 0) {
- timeout();
- }
-
- return TextView::tick();
-}
-
-void Location::timeout() {
- redraw();
-}
-
} // namespace Locations
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/location.h b/engines/mm/mm1/views/locations/location.h
index 0c96be8783b..fa485d464e1 100644
--- a/engines/mm/mm1/views/locations/location.h
+++ b/engines/mm/mm1/views/locations/location.h
@@ -69,21 +69,11 @@ protected:
*/
void backpackFull();
- /**
- * Set a delay countdown
- */
- void delaySeconds(uint seconds);
-
/**
* Change character
*/
virtual void changeCharacter(uint index);
- /**
- * Called when an active timeout countdown expired
- */
- virtual void timeout();
-
public:
Location(const Common::String &name);
virtual ~Location() {}
@@ -92,11 +82,6 @@ public:
* Draws the initial display for the business
*/
void draw() override;
-
- /**
- * Frame tick
- */
- bool tick() override;
};
} // namespace Locations
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 8034511f8b3..b26800f40cc 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -127,6 +127,22 @@ void TextView::escToGoBack(int x) {
writeString(x, 24, STRING["dialogs.misc.go_back"]);
}
+void TextView::delaySeconds(uint seconds) {
+ _timeoutCtr = seconds * FRAME_RATE;
+}
+
+bool TextView::tick() {
+ if (_timeoutCtr && --_timeoutCtr == 0) {
+ timeout();
+ }
+
+ return UIElement::tick();
+}
+
+void TextView::timeout() {
+ redraw();
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 58d5f0821c7..2761fa1c40e 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -33,6 +33,8 @@ namespace Views {
#define TEXT_H 25
class TextView : public UIElement {
+private:
+ int _timeoutCtr = 0;
protected:
Common::Point _textPos;
@@ -78,10 +80,28 @@ protected:
* Prints a message 'ESC' to go back
*/
void escToGoBack(int x = 12);
+
+ /**
+ * Set a delay countdown
+ */
+ void delaySeconds(uint seconds);
+
+ /**
+ * Called when an active timeout countdown expired
+ */
+ virtual void timeout();
+
public:
TextView(const Common::String &name);
TextView(const Common::String &name, UIElement *owner);
virtual ~TextView() {}
+
+ /**
+ * Frame tick
+ */
+ bool tick() override;
+
+
};
} // namespace Views
Commit: 5041dc79bc0e19e39e25cff3ae3479ac809c4159
https://github.com/scummvm/scummvm/commit/5041dc79bc0e19e39e25cff3ae3479ac809c4159
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Logic for remove item
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/character_info.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 6c1bcdc4913..c23db05ca4e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -37,6 +37,7 @@ dialogs:
full: "*** FULL ***"
have_missile: "*** AREADY HAVE MISSILE WEAPON ***"
wrong_alignment: "*** WRONG ALIGNMENT ***"
+ cursed: "*** CURSED ***"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 161eb092977..e22e44601ac 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -271,14 +271,70 @@ void CharacterInfo::equipItem(uint index) {
writeString(equipError);
Sound::sound(SOUND_2);
- delaySeconds(5);
+ delaySeconds(3);
}
_state = DISPLAY;
}
void CharacterInfo::removeItem(uint index) {
+ Character &c = *g_globals->_currCharacter;
+ uint itemId = c._equipped[index];
+ uint item14 = c._equipped14[index];
+
+ Common::String removeError;
+
+ getItem(itemId);
+ const Item &item = g_globals->_currItem;
+ if (item._equipMode == EQUIP_CURSED) {
+ removeError = STRING["dialogs.character.cursed"];
+ _textPos.x = 13;
+ } else if (c._backpack.full()) {
+ removeError = STRING["dialogs.character.full"];
+ _textPos.x = 14;
+ }
+
+ _state = DISPLAY;
+
+ if (!removeError.empty()) {
+ clearLines(20, 24);
+ _textPos.y = 21;
+ writeString(removeError);
+ Sound::sound(SOUND_2);
+ delaySeconds(3);
+ return;
+ }
+
+ // Shift item to backpack
+ int freeIndex = c._backpack.getFreeSlot();
+ c._backpack[freeIndex] = itemId;
+ c._backpack14[freeIndex] = item14;
+ c._equipped[index] = 0;
+ c._equipped14[index] = 0;
+
+ if (item._val10) {
+ // TODO: This block doesn't make sense in the original.
+ // It uses the item._equipMode as an arbitrary array
+ // index into the character data.
+ error("TODO: item flag in remove item");
+ }
+
+ switch (getItemCategory(itemId)) {
+ case ITEMCAT_WEAPON:
+ case ITEMCAT_TWO_HANDED:
+ c._v68 = c._v69 = 0;
+ break;
+ case ITEMCAT_MISSILE:
+ c._v6a = c._v6b = 0;
+ break;
+ case ITEMCAT_ARMOR:
+ case ITEMCAT_SHIELD:
+ c._acBase = MAX((int)c._acBase - (int)item._val17, 0);
+ break;
+ default:
+ break;
+ }
}
} // namespace Views
Commit: 722c6104394b78344465ca1026984eb2748e8b3c
https://github.com/scummvm/scummvm/commit/722c6104394b78344465ca1026984eb2748e8b3c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Share function of character info
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/meta_engine.cpp
engines/mm/mm1/meta_engine.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c23db05ca4e..bb08d74ad92 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1,4 +1,4 @@
-dialogs:
+ dialogs:
location:
titles:
0: "--TRAINING--"
@@ -38,6 +38,13 @@ dialogs:
have_missile: "*** AREADY HAVE MISSILE WEAPON ***"
wrong_alignment: "*** WRONG ALIGNMENT ***"
cursed: "*** CURSED ***"
+ share_all: "SHARE ALL:"
+ gather_all: "GATHER ALL:"
+ trade_which: "TRADE WHICH:"
+ gems: "1) GEMS"
+ gold: "2) GOLD"
+ food: "3) FOOD"
+ item: "4) ITEM"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index 7c611d7c5c6..5b4d69132dd 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -38,6 +38,10 @@ struct KeybindingRecord {
static const KeybindingRecord MENU_KEYS[] = {
{ KEYBIND_ESCAPE, "ESCAPE", "Escape", "ESC", nullptr },
+ { KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
+};
+
+static const KeybindingRecord PARTY_KEYS[] = {
{ KEYBIND_VIEW_PARTY1, "PARTY1", "View Party Member 1", "1", nullptr },
{ KEYBIND_VIEW_PARTY2, "PARTY2", "View Party Member 2", "2", nullptr },
{ KEYBIND_VIEW_PARTY3, "PARTY3", "View Party Member 3", "3", nullptr },
@@ -63,12 +67,6 @@ static const KeybindingRecord NORMAL_KEYS[] = {
{ KEYBIND_BASH, "BASH", "Bash", "b", nullptr },
{ KEYBIND_UNLOCK, "UNLOCK", "Unlock", "u", nullptr },
{ KEYBIND_QUICKREF, "QUICKREF", "Quick Reference", "q", nullptr },
- { KEYBIND_VIEW_PARTY1, "PARTY1", "View Party Member 1", "1", nullptr },
- { KEYBIND_VIEW_PARTY2, "PARTY2", "View Party Member 2", "2", nullptr },
- { KEYBIND_VIEW_PARTY3, "PARTY3", "View Party Member 3", "3", nullptr },
- { KEYBIND_VIEW_PARTY4, "PARTY4", "View Party Member 4", "4", nullptr },
- { KEYBIND_VIEW_PARTY5, "PARTY5", "View Party Member 5", "5", nullptr },
- { KEYBIND_VIEW_PARTY6, "PARTY6", "View Party Member 6", "6", nullptr },
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
};
@@ -89,15 +87,24 @@ static const KeysRecord MENU_RECORDS[] = {
{ nullptr, nullptr, nullptr }
};
+static const KeysRecord PARTY_MENU_RECORDS[] = {
+ { "mm1", "Might and Magic 1 - Menus", MENU_KEYS },
+ { "mm1_party", "Might and Magic 1 - Party", PARTY_KEYS },
+ { nullptr, nullptr, nullptr }
+};
+
static const KeysRecord NORMAL_RECORDS[] = {
{ "mm1", "Might and Magic 1", NORMAL_KEYS },
+ { "mm1_party", "Might and Magic 1 - Party", PARTY_KEYS },
{ "mm1_cheats", "Might and Magic 1 - Cheats", CHEAT_KEYS },
{ nullptr, nullptr, nullptr }
};
-static const KeysRecord *MODE_RECORDS[2] = {
+static const KeysRecord *MODE_RECORDS[4] = {
MENU_RECORDS,
- NORMAL_RECORDS
+ PARTY_MENU_RECORDS,
+ NORMAL_RECORDS,
+ nullptr // TODO: combat keybindings
};
Common::KeymapArray MetaEngine::initKeymaps(KeybindingMode mode) {
diff --git a/engines/mm/mm1/meta_engine.h b/engines/mm/mm1/meta_engine.h
index 770bb7f73d4..d092acd8d27 100644
--- a/engines/mm/mm1/meta_engine.h
+++ b/engines/mm/mm1/meta_engine.h
@@ -67,9 +67,10 @@ enum KeybindingAction {
};
enum KeybindingMode {
- KBMODE_MENUS, ///< Keys for when showing menus
- KBMODE_NORMAL, ///< Keys available when normal in-game
- KBMODE_COMBAT ///< Keys when in combat mode
+ KBMODE_MENUS, ///< Keys for when showing menus
+ KBMODE_PARTY_MENUS, ///< Keys for menus that allow switching party members
+ KBMODE_NORMAL, ///< Keys available when normal in-game
+ KBMODE_COMBAT ///< Keys when in combat mode
};
class MetaEngine {
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index e22e44601ac..aa8078c9869 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -32,6 +32,11 @@ void CharacterInfo::draw() {
assert(g_globals->_currCharacter);
CharacterBase::draw();
+ MetaEngine::setKeybindingMode(_state == DISPLAY ?
+ KeybindingMode::KBMODE_PARTY_MENUS :
+ KeybindingMode::KBMODE_MENUS
+ );
+
switch (_state) {
case DISPLAY:
writeString(0, 21, STRING["dialogs.character.legend1"]);
@@ -49,6 +54,14 @@ void CharacterInfo::draw() {
writeString(0, 20, STRING["dialogs.chracter.remove"]);
escToGoBack(0);
break;
+
+ case SHARE:
+ writeString(8, 20, STRING["dialogs.character.share_all"]);
+ drawGemsGoldFood();
+ break;
+
+ default:
+ break;
}
}
@@ -70,6 +83,7 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_e:
if (!g_globals->_currCharacter->_backpack.empty())
_state = EQUIP;
+ redraw();
break;
case Common::KEYCODE_g:
g_globals->_currCharacter->gatherGold();
@@ -81,6 +95,11 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_r:
if (!g_globals->_currCharacter->_equipped.empty())
_state = REMOVE;
+ redraw();
+ break;
+ case Common::KEYCODE_s:
+ _state = SHARE;
+ redraw();
break;
default:
break;
@@ -94,6 +113,19 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
break;
case REMOVE:
+ if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_6)
+ removeItem(msg.keycode - Common::KEYCODE_1);
+ break;
+
+ case SHARE:
+ if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_3) {
+ share((ShareType)(msg.keycode - Common::KEYCODE_1));
+ _state = DISPLAY;
+ redraw();
+ break;
+ }
break;
default:
@@ -337,6 +369,37 @@ void CharacterInfo::removeItem(uint index) {
}
}
+#define SHARE_FIELD(FIELD) \
+ for (uint i = 0; i < party.size(); ++i) \
+ total += party[i].FIELD; \
+ avg = total / party.size(); \
+ party[0].FIELD = avg + (total % party.size()); \
+ for (uint i = 1; i < party.size(); ++i) \
+ party[i].FIELD = avg;
+
+void CharacterInfo::share(ShareType shareType) {
+ auto &party = g_globals->_party;
+ int total = 0, avg;
+
+ switch (shareType) {
+ case GEMS:
+ SHARE_FIELD(_gems);
+ break;
+ case GOLD:
+ SHARE_FIELD(_gold);
+ break;
+ case FOOD:
+ SHARE_FIELD(_food);
+ break;
+ }
+}
+
+void CharacterInfo::drawGemsGoldFood() {
+ writeString(20, 20, STRING["dialogs.character.gems"]);
+ writeString(20, 21, STRING["dialogs.character.gold"]);
+ writeString(20, 22, STRING["dialogs.character.food"]);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 59b397022c7..30d60adfd86 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -34,7 +34,7 @@ namespace Views {
*/
class CharacterInfo : public CharacterBase {
private:
- enum ViewState { DISPLAY = 0, EQUIP = 1, REMOVE = 2 };
+ enum ViewState { DISPLAY, EQUIP, GATHER, REMOVE, SHARE };
ViewState _state = DISPLAY;
Common::String _newName;
private:
@@ -47,6 +47,17 @@ private:
* Removes the equipped item at the given index
*/
void removeItem(uint index);
+
+ /**
+ * Shares gems, gold or food
+ */
+ enum ShareType { GEMS = 0, GOLD = 1, FOOD = 2 };
+ void share(ShareType shareType);
+
+ /**
+ * Draw options for gems, gold, and food
+ */
+ void drawGemsGoldFood();
public:
CharacterInfo() : CharacterBase("CharacterInfo") {}
virtual ~CharacterInfo() {}
Commit: 3f9f7b0f6f794e7dd3d890fac19bec78f70b60ee
https://github.com/scummvm/scummvm/commit/3f9f7b0f6f794e7dd3d890fac19bec78f70b60ee
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Moved share method to new Party class
Changed paths:
A engines/mm/mm1/data/party.cpp
A engines/mm/mm1/data/party.h
engines/mm/mm1/data/game_state.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index 3ab55958207..442af705638 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -26,6 +26,7 @@
#include "common/rect.h"
#include "common/serializer.h"
#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/party.h"
namespace MM {
namespace MM1 {
@@ -63,7 +64,7 @@ union ActiveSpells {
* that is persisted to savegames
*/
struct GameState {
- Common::Array<Character> _party;
+ Party _party;
ActiveSpells _spells;
GameState();
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
new file mode 100644
index 00000000000..74ce27a7f7e
--- /dev/null
+++ b/engines/mm/mm1/data/party.cpp
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/party.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+
+#define SHARE_FIELD(FIELD) \
+ for (uint i = 0; i < party.size(); ++i) \
+ total += party[i].FIELD; \
+ avg = total / party.size(); \
+ party[0].FIELD = avg + (total % party.size()); \
+ for (uint i = 1; i < party.size(); ++i) \
+ party[i].FIELD = avg;
+
+void Party::share(ShareType shareType) {
+ auto &party = g_globals->_party;
+ int total = 0, avg;
+
+ switch (shareType) {
+ case GEMS:
+ SHARE_FIELD(_gems);
+ break;
+ case GOLD:
+ SHARE_FIELD(_gold);
+ break;
+ case FOOD:
+ SHARE_FIELD(_food);
+ break;
+ }
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
new file mode 100644
index 00000000000..74974a833da
--- /dev/null
+++ b/engines/mm/mm1/data/party.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_PARTY_H
+#define MM1_DATA_PARTY_H
+
+#include "common/array.h"
+#include "mm/mm1/data/char.h"
+
+namespace MM {
+namespace MM1 {
+
+struct Party : public Common::Array<Character> {
+ /**
+ * Shares gems, gold or food
+ */
+ enum ShareType {
+ GEMS = 0, GOLD = 1, FOOD = 2
+ };
+ static void share(ShareType shareType);
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index aa8078c9869..8365c764edd 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -121,7 +121,7 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case SHARE:
if (msg.keycode >= Common::KEYCODE_1 &&
msg.keycode <= Common::KEYCODE_3) {
- share((ShareType)(msg.keycode - Common::KEYCODE_1));
+ Party::share((Party::ShareType)(msg.keycode - Common::KEYCODE_1));
_state = DISPLAY;
redraw();
break;
@@ -369,31 +369,6 @@ void CharacterInfo::removeItem(uint index) {
}
}
-#define SHARE_FIELD(FIELD) \
- for (uint i = 0; i < party.size(); ++i) \
- total += party[i].FIELD; \
- avg = total / party.size(); \
- party[0].FIELD = avg + (total % party.size()); \
- for (uint i = 1; i < party.size(); ++i) \
- party[i].FIELD = avg;
-
-void CharacterInfo::share(ShareType shareType) {
- auto &party = g_globals->_party;
- int total = 0, avg;
-
- switch (shareType) {
- case GEMS:
- SHARE_FIELD(_gems);
- break;
- case GOLD:
- SHARE_FIELD(_gold);
- break;
- case FOOD:
- SHARE_FIELD(_food);
- break;
- }
-}
-
void CharacterInfo::drawGemsGoldFood() {
writeString(20, 20, STRING["dialogs.character.gems"]);
writeString(20, 21, STRING["dialogs.character.gold"]);
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 30d60adfd86..181675cdfbc 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -48,12 +48,6 @@ private:
*/
void removeItem(uint index);
- /**
- * Shares gems, gold or food
- */
- enum ShareType { GEMS = 0, GOLD = 1, FOOD = 2 };
- void share(ShareType shareType);
-
/**
* Draw options for gems, gold, and food
*/
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c7e1b407be0..0864a71cace 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -15,6 +15,7 @@ MODULE_OBJS := \
mm1/data/char.o \
mm1/data/game_state.o \
mm1/data/items.o \
+ mm1/data/party.o \
mm1/data/roster.o \
mm1/game/search.o \
mm1/game/view_base.o \
Commit: 2164d978d004d001cd1f5343b68f9e6737c38b85
https://github.com/scummvm/scummvm/commit/2164d978d004d001cd1f5343b68f9e6737c38b85
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Created generic text entry view
Changed paths:
A engines/mm/mm1/views/text_entry.cpp
A engines/mm/mm1/views/text_entry.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index bb08d74ad92..03f00d98ec2 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -40,11 +40,13 @@
cursed: "*** CURSED ***"
share_all: "SHARE ALL:"
gather_all: "GATHER ALL:"
+ trade_with: "TRADE WITH: '1'-'%d'"
trade_which: "TRADE WHICH:"
gems: "1) GEMS"
gold: "2) GOLD"
food: "3) FOOD"
item: "4) ITEM"
+ how_much: "HOW MUCH:"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
@@ -246,7 +248,7 @@
full: "*** BACKPACK FULL ***"
stats:
none: "NONE"
- inventory: "-----<EQUIPPED>----------<BACKPACK>----".
+ inventory: "-----<EQUIPPED>----------<BACKPACK>----"
classes:
1: "KNIGHT"
2: "PALADIN"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index e2c5a00f8c3..9135e9c272d 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -44,6 +44,11 @@ enum EquipMode {
EQUIP_CURSED = 0xff
};
+enum TransferKind {
+ TK_GEMS = 1, TK_GOLD = 2, TK_FOOD = 3, TK_ITEM = 4
+};
+
+
struct ItemData {
byte _disablements;
EquipMode _equipMode;
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 74ce27a7f7e..83a36293d4d 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -33,18 +33,18 @@ namespace MM1 {
for (uint i = 1; i < party.size(); ++i) \
party[i].FIELD = avg;
-void Party::share(ShareType shareType) {
+void Party::share(TransferKind shareType) {
auto &party = g_globals->_party;
int total = 0, avg;
switch (shareType) {
- case GEMS:
+ case TK_GEMS:
SHARE_FIELD(_gems);
break;
- case GOLD:
+ case TK_GOLD:
SHARE_FIELD(_gold);
break;
- case FOOD:
+ case TK_FOOD:
SHARE_FIELD(_food);
break;
}
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index 74974a833da..fc1e166fcaf 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -29,13 +29,7 @@ namespace MM {
namespace MM1 {
struct Party : public Common::Array<Character> {
- /**
- * Shares gems, gold or food
- */
- enum ShareType {
- GEMS = 0, GOLD = 1, FOOD = 2
- };
- static void share(ShareType shareType);
+ static void share(TransferKind shareType);
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 8365c764edd..26777588acd 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -32,7 +32,8 @@ void CharacterInfo::draw() {
assert(g_globals->_currCharacter);
CharacterBase::draw();
- MetaEngine::setKeybindingMode(_state == DISPLAY ?
+ MetaEngine::setKeybindingMode(
+ _state == DISPLAY || _state == TRADE_WITH ?
KeybindingMode::KBMODE_PARTY_MENUS :
KeybindingMode::KBMODE_MENUS
);
@@ -46,12 +47,12 @@ void CharacterInfo::draw() {
break;
case EQUIP:
- writeString(0, 20, STRING["dialogs.chracter.equip"]);
+ writeString(0, 20, STRING["dialogs.character.equip"]);
escToGoBack(0);
break;
case REMOVE:
- writeString(0, 20, STRING["dialogs.chracter.remove"]);
+ writeString(0, 20, STRING["dialogs.character.remove"]);
escToGoBack(0);
break;
@@ -60,6 +61,32 @@ void CharacterInfo::draw() {
drawGemsGoldFood();
break;
+ case TRADE_WITH:
+ // Print party
+ clearLines(13, 24);
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ const Character &c = g_globals->_party[i];
+ _textPos.x = (i % 2) == 0 ? 1 : 22;
+ _textPos.y = 15 + (i / 2);
+ writeChar(c._condition ? '*' : ' ');
+ writeChar('1' + i);
+ writeString(") ");
+ writeString(c._name);
+ }
+
+ writeString(10, 20, Common::String::format(
+ STRING["dialogs.character.trade_with"].c_str(),
+ (int)g_globals->_party.size()
+ ));
+ break;
+
+ case TRADE_KIND:
+ writeString(6, 20, STRING["dialogs.character.trade_which"]);
+ drawGemsGoldFood();
+ writeString(20, 23, STRING["dialogs.character.item"]);
+ escToGoBack(0);
+ break;
+
default:
break;
}
@@ -101,6 +128,10 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
_state = SHARE;
redraw();
break;
+ case Common::KEYCODE_t:
+ _state = TRADE_WITH;
+ redraw();
+ break;
default:
break;
}
@@ -121,13 +152,40 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case SHARE:
if (msg.keycode >= Common::KEYCODE_1 &&
msg.keycode <= Common::KEYCODE_3) {
- Party::share((Party::ShareType)(msg.keycode - Common::KEYCODE_1));
+ Party::share((TransferKind)(msg.keycode - Common::KEYCODE_0));
_state = DISPLAY;
redraw();
break;
}
break;
+ case TRADE_KIND:
+ if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_3) {
+ _tradeKind = (TransferKind)(msg.keycode - Common::KEYCODE_0);
+
+ clearLines(20, 24);
+ escToGoBack(0);
+ writeString(10, 20, STRING["dialogs.character.how_much"]);
+
+ _textEntry.display(20, 20, 5, true,
+ []() {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->howMuchAborted();
+ },
+ [](const Common::String &text) {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->howMuchEntered(atoi(text.c_str()));
+ }
+ );
+
+ } else if (msg.keycode == Common::KEYCODE_4) {
+ // TODO: Trade item
+ }
+ break;
+
default:
break;
}
@@ -137,14 +195,19 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
bool CharacterInfo::msgAction(const ActionMessage &msg) {
if (msg._action >= KEYBIND_VIEW_PARTY1 &&
- msg._action <= KEYBIND_VIEW_PARTY6 &&
- _state == DISPLAY) {
- g_globals->_currCharacter = &g_globals->_party[
- msg._action - KEYBIND_VIEW_PARTY1];
- addView();
- return true;
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ if (_state == DISPLAY) {
+ g_globals->_currCharacter = &g_globals->_party[
+ msg._action - KEYBIND_VIEW_PARTY1];
+ addView();
+ return true;
+ } else if (_state == TRADE_WITH) {
+ _state = TRADE_KIND;
+ _tradeWith = msg._action - KEYBIND_VIEW_PARTY1;
+ redraw();
+ return true;
+ }
}
-
return false;
}
@@ -375,6 +438,15 @@ void CharacterInfo::drawGemsGoldFood() {
writeString(20, 22, STRING["dialogs.character.food"]);
}
+void CharacterInfo::howMuchAborted() {
+ _state = TRADE_WITH;
+ redraw();
+}
+
+void CharacterInfo::howMuchEntered(int amount) {
+
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 181675cdfbc..4b248ada3bc 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -24,6 +24,8 @@
#include "common/array.h"
#include "mm/mm1/views/character_base.h"
+#include "mm/mm1/data/items.h"
+#include "mm/mm1/views/text_entry.h"
namespace MM {
namespace MM1 {
@@ -34,9 +36,15 @@ namespace Views {
*/
class CharacterInfo : public CharacterBase {
private:
- enum ViewState { DISPLAY, EQUIP, GATHER, REMOVE, SHARE };
+ enum ViewState {
+ DISPLAY, EQUIP, GATHER, REMOVE, SHARE,
+ TRADE_WITH, TRADE_KIND, TRADE_WHAT };
ViewState _state = DISPLAY;
Common::String _newName;
+private:
+ int _tradeWith = -1;
+ TransferKind _tradeKind = TK_GEMS;
+ TextEntry _textEntry;
private:
/**
* Equips the item at the given index
@@ -59,6 +67,16 @@ public:
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
+
+ /**
+ * How much entry aborted
+ */
+ void howMuchAborted();
+
+ /**
+ * How much entered for a trade
+ */
+ void howMuchEntered(int amount);
};
diff --git a/engines/mm/mm1/views/text_entry.cpp b/engines/mm/mm1/views/text_entry.cpp
new file mode 100644
index 00000000000..472e66c49a4
--- /dev/null
+++ b/engines/mm/mm1/views/text_entry.cpp
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/text_entry.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void TextEntry::display(int x, int y, int maxLen,
+ bool isNumeric, Abort abortFn, Enter enterFn) {
+ _maxLen = maxLen;
+ _abortFn = abortFn;
+ _enterFn = enterFn;
+ _isNumeric = isNumeric;
+ _text = "";
+ _bounds = Common::Rect(x * 8, y * 8,
+ (x + maxLen + 1) * 8, (y + 1) * 8);
+
+ addView(this);
+}
+
+void TextEntry::draw() {
+ clearSurface();
+ writeString(_text);
+ writeChar('_');
+}
+
+bool TextEntry::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ _abortFn();
+ return true;
+ } else if (msg.keycode == Common::KEYCODE_RETURN &&
+ !_text.empty()) {
+ close();
+ _enterFn(_text);
+ return true;
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
+ !_text.empty()) {
+ _text.deleteLastChar();
+ redraw();
+ return true;
+ } else if (msg.ascii >= 32 && msg.ascii <= 127 &&
+ _text.size() < _maxLen) {
+ if (_isNumeric && (msg.ascii <= '0' || msg.ascii >= '9'))
+ return true;
+
+ _text += msg.ascii;
+ redraw();
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/text_entry.h b/engines/mm/mm1/views/text_entry.h
new file mode 100644
index 00000000000..2cfc0302235
--- /dev/null
+++ b/engines/mm/mm1/views/text_entry.h
@@ -0,0 +1,57 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_TEXT_ENTRY_H
+#define MM1_VIEWS_TEXT_ENTRY_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+/**
+ * Text or numeric entry.
+ */
+class TextEntry : public TextView {
+public:
+ typedef void (*Abort)();
+ typedef void (*Enter)(const Common::String &text);
+ Abort _abortFn;
+ Enter _enterFn;
+ bool _isNumeric = false;
+ Common::String _text;
+ size_t _maxLen = 0;
+public:
+ TextEntry() : TextView("TextEntry") {}
+ virtual ~TextEntry() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void display(int x, int y, int maxLen, bool isNumeric,
+ Abort abortFn, Enter enterFn);
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 0864a71cace..c6539a32d40 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -54,6 +54,7 @@ MODULE_OBJS := \
mm1/views/quick_ref.o \
mm1/views/statue.o \
mm1/views/title.o \
+ mm1/views/text_entry.o \
mm1/views/text_view.o \
mm1/views_enh/button_container.o \
mm1/views_enh/dialogs.o \
Commit: 395f5695dbc0e50c63e7852a3a51ce7380262e2a
https://github.com/scummvm/scummvm/commit/395f5695dbc0e50c63e7852a3a51ce7380262e2a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Finished trading gems, gold, food
Changed paths:
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 26777588acd..fe8228246d6 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -443,8 +443,42 @@ void CharacterInfo::howMuchAborted() {
redraw();
}
-void CharacterInfo::howMuchEntered(int amount) {
+void CharacterInfo::howMuchEntered(uint amount) {
+ Character &src = *g_globals->_currCharacter;
+ Character &dest = g_globals->_party[_tradeWith];
+
+ switch (_tradeKind) {
+ case TK_GEMS:
+ if (amount > src._gems || ((int)dest._gems + amount) > 0xffff) {
+ Sound::sound(SOUND_2);
+ } else {
+ src._gems -= amount;
+ dest._gems += amount;
+ }
+ break;
+ case TK_GOLD:
+ if (amount > src._gold || (dest._gold + amount) > 0xffffff) {
+ Sound::sound(SOUND_2);
+ } else {
+ src._gold -= amount;
+ dest._gold += amount;
+ }
+ break;
+ case TK_FOOD:
+ if (amount > src._food || (dest._food + amount) > 40) {
+ Sound::sound(SOUND_2);
+ } else {
+ src._food -= amount;
+ dest._food += amount;
+ }
+ break;
+ default:
+ break;
+ }
+
+ _state = DISPLAY;
+ redraw();
}
} // namespace Views
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 4b248ada3bc..e6899a7928e 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -76,7 +76,7 @@ public:
/**
* How much entered for a trade
*/
- void howMuchEntered(int amount);
+ void howMuchEntered(uint amount);
};
Commit: 0253ded66e77672f77e4295fb2d30a3caa30ea90
https://github.com/scummvm/scummvm/commit/0253ded66e77672f77e4295fb2d30a3caa30ea90
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Implementing most of item trade
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 03f00d98ec2..77f0dddebac 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -27,6 +27,7 @@
legend4: "'ESC' TO GO BACK 'G' GATHER 'U' USE"
equip: "EQUIP WHICH ITEM: 'A'-'F'?"
remove: "REMOVE WHICH ITEM: '1'-'6'?"
+ which: "WHICH ITEM: 'A'-'F'?"
wrong_class: "*** WRONG CLASS ***"
have_armor: "*** ALREADY WEARING ARMOR ***"
not_equipped: "*** NOT EQUIPPED ***"
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 57cb00e9d64..9c9329fd9c9 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -173,6 +173,22 @@ void Character::gatherGold() {
_gold = total;
}
+Character::TradeResult Character::trade(int whoTo, int itemIndex) {
+ Character &dest = g_globals->_party[whoTo];
+ if (&dest == this)
+ return TRADE_SUCCESS;
+
+ if (dest._backpack.full())
+ return TRADE_FULL;
+ if (!_backpack[itemIndex])
+ return TRADE_NO_ITEM;
+
+ // TODO: do the trade
+
+ return TRADE_SUCCESS;
+}
+
+
Character::LevelIncrease Character::increaseLevel() {
_level = ++_levelBase;
_age = ++_ageBase;
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index d9bdd540646..60aac9a261f 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -182,6 +182,12 @@ struct Character {
*/
void gatherGold();
+ /**
+ * Trade an item to another
+ */
+ enum TradeResult { TRADE_SUCCESS, TRADE_NO_ITEM, TRADE_FULL };
+ TradeResult trade(int whoTo, int itemIndex);
+
/**
* Increase the character's level by 1 at a trainer
*/
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index fe8228246d6..cdfd088fe9b 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -87,6 +87,11 @@ void CharacterInfo::draw() {
escToGoBack(0);
break;
+ case TRADE_ITEM:
+ writeString(10, 20, STRING["dialogs.character.which"]);
+ escToGoBack(0);
+ break;
+
default:
break;
}
@@ -182,7 +187,36 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
);
} else if (msg.keycode == Common::KEYCODE_4) {
- // TODO: Trade item
+ if (g_globals->_party[_tradeWith]._backpack.full()) {
+ writeString(14, 21, STRING["dialogs.character.full"]);
+ Sound::sound(SOUND_2);
+ _state = DISPLAY;
+ delaySeconds(3);
+ } else {
+ _state = TRADE_ITEM;
+ redraw();
+ }
+ }
+ break;
+
+ case TRADE_ITEM:
+ if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode <= Common::KEYCODE_f) {
+ switch (g_globals->_currCharacter->trade(_tradeWith,
+ msg.keycode - Common::KEYCODE_a)) {
+ case Character::TRADE_FULL:
+ writeString(14, 21, STRING["dialogs.character.full"]);
+ _state = DISPLAY;
+ delaySeconds(3);
+ break;
+ case Character::TRADE_SUCCESS:
+ _state = DISPLAY;
+ redraw();
+ break;
+ default:
+ // Do nothing, no item at selected index
+ break;
+ }
}
break;
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index e6899a7928e..cd291f7c09c 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -38,7 +38,7 @@ class CharacterInfo : public CharacterBase {
private:
enum ViewState {
DISPLAY, EQUIP, GATHER, REMOVE, SHARE,
- TRADE_WITH, TRADE_KIND, TRADE_WHAT };
+ TRADE_WITH, TRADE_KIND, TRADE_ITEM };
ViewState _state = DISPLAY;
Common::String _newName;
private:
Commit: 502a2327fd8c4dd051dade2643a3406db8d364b6
https://github.com/scummvm/scummvm/commit/502a2327fd8c4dd051dade2643a3406db8d364b6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:58+01:00
Commit Message:
MM: MM1: Merge id/v14 inventories into single Inventory class
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 9c9329fd9c9..7de9f81ff95 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -35,8 +35,9 @@ void Inventory::clear() {
_items.resize(INVENTORY_COUNT);
}
-void Inventory::synchronize(Common::Serializer &s) {
- s.syncBytes(&_items[0], INVENTORY_COUNT);
+void Inventory::synchronize(Common::Serializer &s, bool ids) {
+ for (int i = 0; i < INVENTORY_COUNT; ++i)
+ s.syncAsByte(ids ? _items[i]._id : _items[i]._field14);
}
bool Inventory::empty() const {
@@ -55,6 +56,14 @@ bool Inventory::full() const {
return true;
}
+uint Inventory::add(byte id, byte field14) {
+ uint idx = getFreeSlot();
+ _items[idx]._id = id;
+ _items[idx]._field14 = field14;
+
+ return idx;
+}
+
int Inventory::getFreeSlot() const {
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
if (!_items[i])
@@ -68,12 +77,12 @@ int Inventory::getFreeSlot() const {
void Inventory::removeAt(uint idx) {
_items.remove_at(idx);
- _items.push_back(0);
+ _items.push_back(Entry());
}
bool Inventory::hasCategory(CategoryFn fn) const {
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
- if (fn(_items[i]))
+ if (fn(_items[i]._id))
return true;
}
return false;
@@ -123,10 +132,10 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_food);
s.syncAsByte(_condition);
- _equipped.synchronize(s);
- _backpack.synchronize(s);
- _equipped14.synchronize(s);
- _backpack14.synchronize(s);
+ _equipped.synchronize(s, true);
+ _backpack.synchronize(s, true);
+ _equipped.synchronize(s, false);
+ _backpack.synchronize(s, false);
// TODO: Figure purpose of remaining unknown fields
s.skip(39);
@@ -154,7 +163,6 @@ void Character::clear() {
_condition = 0;
_equipped.clear();
_backpack.clear();
- _backpack14.clear();
_alignmentInitial = GOOD;
_alignment = GOOD;
@@ -281,8 +289,7 @@ Character::BuyResult Character::buyItem(byte itemId) {
// Add the item
_gold -= item._cost;
- _backpack[slotIndex] = itemId;
- _backpack14[slotIndex] = item._val13;
+ _backpack.add(itemId, item._val13);
return BUY_SUCCESS;
}
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 60aac9a261f..90bda28aba9 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -57,23 +57,37 @@ enum Condition {
};
class Inventory {
+public:
+ struct Entry {
+ byte _id = 0;
+ byte _field14 = 0;
+ operator bool() const { return _id != 0; }
+// bool operator!() const { return !_id; }
+// operator byte() const { return _id; }
+ };
private:
- Common::Array<byte> _items;
+ Common::Array<Entry> _items;
/**
* Used to test if the inventory has a category of item
*/
typedef bool (*CategoryFn)(byte id);
bool hasCategory(CategoryFn fn) const;
+
+ /**
+ * Returns the index of a free slot
+ */
+ int getFreeSlot() const;
+
public:
Inventory() {
clear();
}
- byte &operator[](uint idx) {
+ Entry &operator[](uint idx) {
assert(idx < INVENTORY_COUNT);
return _items[idx];
}
- const byte &operator[](uint idx) const {
+ const Entry &operator[](uint idx) const {
assert(idx < INVENTORY_COUNT);
return _items[idx];
}
@@ -81,7 +95,7 @@ public:
/**
* Saves or loads the inventory data
*/
- void synchronize(Common::Serializer &s);
+ void synchronize(Common::Serializer &s, bool ids);
/**
* Clears the inventory
@@ -99,9 +113,9 @@ public:
bool full() const;
/**
- * Returns the index of a free slot
+ * Adds an item to the inventory
*/
- int getFreeSlot() const;
+ uint add(byte id, byte field14);
/**
* Removes an index from the inventory
@@ -149,8 +163,6 @@ struct Character {
uint8 _condition = 0;
Inventory _equipped;
Inventory _backpack;
- Inventory _equipped14;
- Inventory _backpack14;
// TODO: Figure out what these are
int _v58, _v59, _v62, _v63, _v64, _v65;
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index cdfd088fe9b..762f6461871 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -247,8 +247,8 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
void CharacterInfo::equipItem(uint index) {
Character &c = *g_globals->_currCharacter;
- uint itemId = c._backpack[index];
- uint item14 = c._backpack14[index];
+ uint itemId = c._backpack[index]._id;
+ uint item14 = c._backpack[index]._field14;
int classBit = 0;
Common::String equipError;
@@ -352,18 +352,14 @@ void CharacterInfo::equipItem(uint index) {
if (equipError.empty()) {
// All checks passed, can equip item
c._backpack.removeAt(index);
- c._backpack14.removeAt(index);
-
- int freeIndex = c._equipped.getFreeSlot();
- c._equipped[freeIndex] = itemId;
- c._equipped14[freeIndex] = item14;
+ uint freeIndex = c._equipped.add(itemId, item14);
if (item._equipMode != EQUIPMODE_0) {
if (item._equipMode == NOT_EQUIPPABLE) {
equipError = STRING["dialogs.character.not_equipped"];
_textPos.x = 10;
} else if (item._equipMode == EQUIP_CURSED) {
- c._equipped14[freeIndex] += item._val10;
+ c._equipped[freeIndex]._field14 += item._val10;
}
}
}
@@ -408,8 +404,8 @@ void CharacterInfo::equipItem(uint index) {
void CharacterInfo::removeItem(uint index) {
Character &c = *g_globals->_currCharacter;
- uint itemId = c._equipped[index];
- uint item14 = c._equipped14[index];
+ uint itemId = c._equipped[index]._id;
+ uint item14 = c._equipped[index]._field14;
Common::String removeError;
@@ -436,11 +432,8 @@ void CharacterInfo::removeItem(uint index) {
}
// Shift item to backpack
- int freeIndex = c._backpack.getFreeSlot();
- c._backpack[freeIndex] = itemId;
- c._backpack14[freeIndex] = item14;
- c._equipped[index] = 0;
- c._equipped14[index] = 0;
+ c._equipped.removeAt(index);
+ c._backpack.add(itemId, item14);
if (item._val10) {
// TODO: This block doesn't make sense in the original.
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index d525cf1ae53..e9459cf78fd 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -124,7 +124,7 @@ void CreateCharacters::NewCharacter::save() {
}
re._food = 10;
- re._backpack[0] = 1;
+ re._backpack[0]._id = 1;
const int ALIGNMENT_VALS[3] = { 0, 0x10, 0x20 };
re._v6f = ALIGNMENT_VALS[re._alignmentInitial];
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index ca98d221527..fc3fa784ee4 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -64,11 +64,10 @@ void BlacksmithSellItem::selectItem(uint index) {
if (index == INVENTORY_COUNT)
return;
- // Clear the slot
- int itemId = c._backpack[index];
- c._backpack[index] = 0;
- int v14 = c._backpack14[index];
- c._backpack14[index] = 0;
+ // Remove the item
+ int itemId = c._backpack[index]._id;
+ int v14 = c._backpack[index]._field14;
+ c._backpack.removeAt(index);
getItem(itemId);
if (!v14 && g_globals->_currItem._val13)
Commit: ad11df142aae4f9f2e54d1e22cc34a1fb4a5becb
https://github.com/scummvm/scummvm/commit/ad11df142aae4f9f2e54d1e22cc34a1fb4a5becb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Finish item trading
Changed paths:
engines/mm/mm1/data/char.cpp
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 7de9f81ff95..6069024f356 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -191,7 +191,9 @@ Character::TradeResult Character::trade(int whoTo, int itemIndex) {
if (!_backpack[itemIndex])
return TRADE_NO_ITEM;
- // TODO: do the trade
+ Inventory::Entry e = _backpack[itemIndex];
+ _backpack.removeAt(itemIndex);
+ dest._backpack.add(e._id, e._field14);
return TRADE_SUCCESS;
}
Commit: dca3ae6b0d3d5b941a4d53b43695f67852df9bf4
https://github.com/scummvm/scummvm/commit/dca3ae6b0d3d5b941a4d53b43695f67852df9bf4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Beginnings of spell casting
Changed paths:
A engines/mm/mm1/data/spells.cpp
A engines/mm/mm1/data/spells.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/data/game_state.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/mm1/views/text_entry.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 77f0dddebac..a0f137303a7 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -48,6 +48,8 @@
food: "3) FOOD"
item: "4) ITEM"
how_much: "HOW MUCH:"
+ cast_spell: "CAST SPELL: LEVEL="
+ number: "NUMBER="
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 6069024f356..50f9e7a6b63 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -30,6 +30,27 @@ static const int CLASS_HP_PER_LEVEL[6] = {
12, 10, 10, 8, 6, 8
};
+static const int8 SPELLS_SP[2][47] = {
+ {
+ 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 2, 0, 2, 2,
+ 0, 0, 0, 3, 3,
+ 4, 4, 4, 4, 4,
+ 10, 5, 5, 5, 5
+ },
+ {
+ 0, 0, -1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0,
+ -1, 0, 1, -1, 0, 0, 1, 0,
+ 0, 0, 2, 0, 0, 2, 2, 2,
+ 0, 0, 3, 3, 3,
+ 4, 4, 4, 4, 4,
+ 5, 100, 5, 5, 5
+ }
+};
+
void Inventory::clear() {
_items.clear();
_items.resize(INVENTORY_COUNT);
@@ -341,5 +362,25 @@ void Character::updateAC() {
_ac = ac;
}
+void Character::castSpell(int lvl, int num) {
+ int lvlNum;
+ int setNum = _class == ARCHER || _class == SORCERER ? 1 : 0;
+
+ // Figure the offset in the spell list
+ int spellNum = 0;
+ for (lvlNum = 2; lvlNum < MIN(lvl, 5); ++lvlNum)
+ spellNum += 8;
+ for (lvlNum = 5; lvlNum < lvl; ++lvlNum)
+ spellNum += 5;
+
+ // Get required SP
+ int requiredSp = SPELLS_SP[setNum][spellNum];
+ if (requiredSp < 0)
+ // required SP increases with character's level
+ requiredSp = _level;
+
+
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 90bda28aba9..459091a0f89 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -225,6 +225,11 @@ struct Character {
* Updates the character's AC
*/
void updateAC();
+
+ /**
+ * Cast a spell
+ */
+ void castSpell(int lvl, int num);
};
} // namespace MM1
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index 442af705638..ad4667e72f9 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -27,38 +27,11 @@
#include "common/serializer.h"
#include "mm/mm1/data/char.h"
#include "mm/mm1/data/party.h"
+#include "mm/mm1/data/spells.h"
namespace MM {
namespace MM1 {
-#define ACTIVE_SPELLS_COUNT 18
-
-struct ActiveSpellsStruct {
- byte fear;
- byte cold;
- byte fire;
- byte poison;
- byte acid;
- byte elec;
- byte magic;
- byte light;
- byte leather_skin;
- byte levitate;
- byte walk_on_water;
- byte guard_dog;
- byte psychic_protecti;
- byte bless;
- byte invisbility;
- byte shield;
- byte power_shield;
- byte cursed;
-};
-
-union ActiveSpells {
- ActiveSpellsStruct _s;
- byte _arr[ACTIVE_SPELLS_COUNT];
-};
-
/**
* This acts as a container for everything in the game
* that is persisted to savegames
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
new file mode 100644
index 00000000000..28d057ccc87
--- /dev/null
+++ b/engines/mm/mm1/data/spells.cpp
@@ -0,0 +1,29 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/spells.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
new file mode 100644
index 00000000000..02442269226
--- /dev/null
+++ b/engines/mm/mm1/data/spells.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_SPELLS_H
+#define MM1_DATA_SPELLS_H
+
+#include "common/scummsys.h"
+
+namespace MM {
+namespace MM1 {
+
+
+#define ACTIVE_SPELLS_COUNT 18
+
+struct ActiveSpellsStruct {
+ byte fear;
+ byte cold;
+ byte fire;
+ byte poison;
+ byte acid;
+ byte elec;
+ byte magic;
+ byte light;
+ byte leather_skin;
+ byte levitate;
+ byte walk_on_water;
+ byte guard_dog;
+ byte psychic_protecti;
+ byte bless;
+ byte invisbility;
+ byte shield;
+ byte power_shield;
+ byte cursed;
+};
+
+union ActiveSpells {
+ ActiveSpellsStruct _s;
+ byte _arr[ACTIVE_SPELLS_COUNT];
+};
+
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 762f6461871..f3f54b4df6a 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -112,6 +112,9 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
switch (_state) {
case DISPLAY:
switch (msg.keycode) {
+ case Common::KEYCODE_c:
+ castSpell();
+ break;
case Common::KEYCODE_e:
if (!g_globals->_currCharacter->_backpack.empty())
_state = EQUIP;
@@ -168,23 +171,7 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode >= Common::KEYCODE_1 &&
msg.keycode <= Common::KEYCODE_3) {
_tradeKind = (TransferKind)(msg.keycode - Common::KEYCODE_0);
-
- clearLines(20, 24);
- escToGoBack(0);
- writeString(10, 20, STRING["dialogs.character.how_much"]);
-
- _textEntry.display(20, 20, 5, true,
- []() {
- CharacterInfo *view =
- (CharacterInfo *)g_events->focusedView();
- view->howMuchAborted();
- },
- [](const Common::String &text) {
- CharacterInfo *view =
- (CharacterInfo *)g_events->focusedView();
- view->howMuchEntered(atoi(text.c_str()));
- }
- );
+ tradeHowMuch();
} else if (msg.keycode == Common::KEYCODE_4) {
if (g_globals->_party[_tradeWith]._backpack.full()) {
@@ -508,6 +495,85 @@ void CharacterInfo::howMuchEntered(uint amount) {
redraw();
}
+void CharacterInfo::tradeHowMuch() {
+ clearLines(20, 24);
+ escToGoBack(0);
+ writeString(10, 20, STRING["dialogs.character.how_much"]);
+
+ _textEntry.display(20, 20, 5, true,
+ []() {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->howMuchAborted();
+ },
+ [](const Common::String &text) {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->howMuchEntered(atoi(text.c_str()));
+ }
+ );
+}
+
+void CharacterInfo::castSpell() {
+ if (g_globals->_currCharacter->_slvl == 0 ||
+ g_globals->_currCharacter->_sp == 0) {
+ // Character can't cast spells, so exit
+ redraw();
+ return;
+ }
+
+ clearLines(20, 24);
+ escToGoBack(0);
+ writeString(7, 20, STRING["dialogs.character.cast_spell"]);
+
+ _textEntry.display(27, 20, 1, true,
+ []() {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->redraw();
+ },
+ [](const Common::String &text) {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->spellLevelEntered(atoi(text.c_str()));
+ }
+ );
+}
+
+void CharacterInfo::spellLevelEntered(uint level) {
+ // Ensure the spell level is valid
+ if (level < 1 || level > 7 ||
+ level > g_globals->_currCharacter->_slvl) {
+ redraw();
+ return;
+ }
+
+ clearLines(21, 21);
+ writeString(19, 21, STRING["dialogs.character.number"]);
+
+ _textEntry.display(27, 21, 1, true,
+ []() {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->redraw();
+ },
+ [](const Common::String &text) {
+ CharacterInfo *view =
+ (CharacterInfo *)g_events->focusedView();
+ view->spellNumberEntered(atoi(text.c_str()));
+ }
+ );
+}
+
+void CharacterInfo::spellNumberEntered(uint num) {
+ if (num < 1 || num > 8 || (_spellLevel >= 5 && num >= 6)) {
+ redraw();
+ return;
+ }
+
+ g_globals->_currCharacter->castSpell(_spellLevel, num);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index cd291f7c09c..4cbb13935d4 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -45,6 +45,7 @@ private:
int _tradeWith = -1;
TransferKind _tradeKind = TK_GEMS;
TextEntry _textEntry;
+ int _spellLevel = -1;
private:
/**
* Equips the item at the given index
@@ -60,6 +61,17 @@ private:
* Draw options for gems, gold, and food
*/
void drawGemsGoldFood();
+
+ /**
+ * Selects how much for gems/gold/food trades
+ */
+ void tradeHowMuch();
+
+ /**
+ * Starts selection of a spell to cast
+ */
+ void castSpell();
+
public:
CharacterInfo() : CharacterBase("CharacterInfo") {}
virtual ~CharacterInfo() {}
@@ -77,6 +89,16 @@ public:
* How much entered for a trade
*/
void howMuchEntered(uint amount);
+
+ /**
+ * Spell level entered for casting
+ */
+ void spellLevelEntered(uint level);
+
+ /**
+ * Spell number within the level entered for casting
+ */
+ void spellNumberEntered(uint num);
};
diff --git a/engines/mm/mm1/views/text_entry.cpp b/engines/mm/mm1/views/text_entry.cpp
index 472e66c49a4..ff91a94e672 100644
--- a/engines/mm/mm1/views/text_entry.cpp
+++ b/engines/mm/mm1/views/text_entry.cpp
@@ -45,15 +45,12 @@ void TextEntry::draw() {
}
bool TextEntry::msgKeypress(const KeypressMessage &msg) {
+ Common::KeyCode kc = msg.keycode;
+
if (msg.keycode == Common::KEYCODE_ESCAPE) {
close();
_abortFn();
return true;
- } else if (msg.keycode == Common::KEYCODE_RETURN &&
- !_text.empty()) {
- close();
- _enterFn(_text);
- return true;
} else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
!_text.empty()) {
_text.deleteLastChar();
@@ -66,6 +63,17 @@ bool TextEntry::msgKeypress(const KeypressMessage &msg) {
_text += msg.ascii;
redraw();
+
+ // Single character numeric fields, particular spell
+ // level/number selection, return immediately
+ if (_isNumeric && _maxLen == 1)
+ kc = Common::KEYCODE_RETURN;
+ }
+
+ if (kc == Common::KEYCODE_RETURN && !_text.empty()) {
+ close();
+ _enterFn(_text);
+ return true;
}
return false;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c6539a32d40..59382d7292b 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS := \
mm1/data/items.o \
mm1/data/party.o \
mm1/data/roster.o \
+ mm1/data/spells.o \
mm1/game/search.o \
mm1/game/view_base.o \
mm1/gfx/dta.o \
Commit: f4a59c9683aa0f50b23fabf2e31fca2d701fce0b
https://github.com/scummvm/scummvm/commit/f4a59c9683aa0f50b23fabf2e31fca2d701fce0b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Scroll window base class for enhanced mode
Changed paths:
A devtools/create_mm/files/mm1/symbols.bin
A engines/mm/mm1/views_enh/character_info.cpp
A engines/mm/mm1/views_enh/character_info.h
A engines/mm/mm1/views_enh/scroll_view.cpp
A engines/mm/mm1/views_enh/scroll_view.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views_enh/dialogs.h
engines/mm/mm1/views_enh/game.cpp
engines/mm/mm1/views_enh/game.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/symbols.bin b/devtools/create_mm/files/mm1/symbols.bin
new file mode 100644
index 00000000000..7ccc2b693d2
Binary files /dev/null and b/devtools/create_mm/files/mm1/symbols.bin differ
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 38a5717f4f4..faf6dbd96a8 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -59,6 +59,12 @@ bool Globals::load(bool isEnhanced) {
_mainIcons.load("main.icn");
_globalSprites.load("global.icn");
_tileSprites.load("town.til");
+
+ Common::File f;
+ if (!f.open("symbols.bin"))
+ error("Could not load symbols.bin");
+ f.read(SYMBOLS, 20 * 64);
+ f.close();
}
return true;
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 95ab783d988..eaf6c218f16 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -50,6 +50,7 @@ public:
Xeen::SpriteResource _mainIcons;
Xeen::SpriteResource _globalSprites;
Xeen::SpriteResource _tileSprites;
+ byte SYMBOLS[20][64];
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index f3f54b4df6a..e58911f1ad5 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -574,6 +574,6 @@ void CharacterInfo::spellNumberEntered(uint num) {
g_globals->_currCharacter->castSpell(_spellLevel, num);
}
-} // namespace Views
+} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
new file mode 100644
index 00000000000..00aa081f9f9
--- /dev/null
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -0,0 +1,35 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/character_info.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+CharacterInfo::CharacterInfo() : ScrollView("CharacterInfo") {
+ _bounds = Common::Rect(0, 0, 320, 146);
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
new file mode 100644
index 00000000000..d62389a8d74
--- /dev/null
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_CHARACTER_INFO_H
+#define MM1_VIEWS_ENH_CHARACTER_INFO_H
+
+#include "mm/mm1/views_enh/scroll_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class CharacterInfo : public ScrollView {
+public:
+ CharacterInfo();
+ virtual ~CharacterInfo() {}
+
+// void draw() override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index 365675719fd..625d0b2de08 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -31,6 +31,7 @@
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
//#include "mm/mm1/views/char.h"
+#include "mm/mm1/views_enh/character_info.h"
#include "mm/mm1/views_enh/game.h"
namespace MM {
@@ -39,6 +40,7 @@ namespace ViewsEnh {
struct Dialogs {
private:
+ ViewsEnh::CharacterInfo _characterInfo;
ViewsEnh::Game _game;
// Unenhanced views
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index 3c646d19ec8..4e6d4d993dd 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -63,6 +63,29 @@ bool Game::msgKeypress(const KeypressMessage &msg) {
return true;
}
+bool Game::msgAction(const ActionMessage &msg) {
+ switch (msg._action) {
+ case KEYBIND_VIEW_PARTY1:
+ case KEYBIND_VIEW_PARTY2:
+ case KEYBIND_VIEW_PARTY3:
+ case KEYBIND_VIEW_PARTY4:
+ case KEYBIND_VIEW_PARTY5:
+ case KEYBIND_VIEW_PARTY6:
+ {
+ uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
+ if (charNum < g_globals->_party.size()) {
+ g_globals->_currCharacter = &g_globals->_party[charNum];
+ addView("CharacterInfo");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TextView::msgAction(msg);
+}
+
bool Game::msgGame(const GameMessage &msg) {
if (msg._name == "DISPLAY") {
replaceView(this);
diff --git a/engines/mm/mm1/views_enh/game.h b/engines/mm/mm1/views_enh/game.h
index f02b429f274..60fe5369777 100644
--- a/engines/mm/mm1/views_enh/game.h
+++ b/engines/mm/mm1/views_enh/game.h
@@ -44,6 +44,7 @@ public:
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
};
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
new file mode 100644
index 00000000000..ff0cf6c852c
--- /dev/null
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -0,0 +1,124 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/scroll_view.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+#define FONT_WIDTH 8
+#define FONT_HEIGHT 8
+
+ScrollView::ScrollView(const Common::String &name) :
+ Views::TextView(name, g_engine) {
+}
+
+void ScrollView::draw() {
+ frame();
+ fill();
+}
+
+void ScrollView::frame() {
+ int xCount = (_bounds.width() - 9) / FONT_WIDTH;
+ int yCount = (_bounds.height() - 9) / FONT_HEIGHT;
+
+ // Write the top line
+ _symbolPos = Common::Point(0, 0);
+ writeSymbol(0);
+
+ if (xCount > 0) {
+ int symbolId = 1;
+ for (int i = 0; i < xCount; ++i) {
+ writeSymbol(symbolId);
+ if (++symbolId == 5)
+ symbolId = 1;
+ }
+ }
+
+ _symbolPos.x = _bounds.width() - FONT_WIDTH;
+ writeSymbol(5);
+
+ // Write the vertical edges
+ if (yCount > 0) {
+ int symbolId = 6;
+ for (int i = 0; i < yCount; ++i) {
+ _symbolPos.y += FONT_HEIGHT;
+
+ _symbolPos.x = 0;
+ writeSymbol(symbolId);
+
+ _symbolPos.x = _bounds.width() - FONT_WIDTH;
+ writeSymbol(symbolId + 4);
+
+ if (++symbolId == 10)
+ symbolId = 6;
+ }
+ }
+
+ // Write the bottom line
+ _symbolPos = Common::Point(0, _bounds.height() - FONT_HEIGHT);
+ writeSymbol(14);
+
+ if (xCount > 0) {
+ int symbolId = 15;
+ for (int i = 0; i < xCount; ++i) {
+ writeSymbol(symbolId);
+ if (++symbolId == 19)
+ symbolId = 15;
+ }
+ }
+
+ _symbolPos.x = _bounds.width() - FONT_WIDTH;
+ writeSymbol(19);
+}
+
+void ScrollView::fill() {
+ Graphics::ManagedSurface s = getSurface();
+ s.fillRect(Common::Rect(8, 8, s.w - 8, s.h - 8), 153);
+}
+
+void ScrollView::writeSymbol(int symbolId) {
+ Graphics::ManagedSurface s = getSurface();
+ const byte *srcP = &g_globals->SYMBOLS[symbolId][0];
+ s.addDirtyRect(Common::Rect(_symbolPos.x, _symbolPos.y,
+ _symbolPos.x + FONT_WIDTH, _symbolPos.y + FONT_HEIGHT));
+
+ for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
+ byte *destP = (byte *)s.getBasePtr(
+ _symbolPos.x, _symbolPos.y + yp);
+
+ for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) {
+ byte b = *srcP++;
+ if (b)
+ *destP = b;
+ }
+ }
+
+ _symbolPos.x += FONT_WIDTH;
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
new file mode 100644
index 00000000000..bcad0264687
--- /dev/null
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_SCROLL_VIEW_H
+#define MM1_VIEWS_ENH_SCROLL_VIEW_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class ScrollView : public Views::TextView {
+protected:
+ Common::Point _symbolPos;
+protected:
+ /**
+ * Draw the scroll frame
+ */
+ void frame();
+
+ /**
+ * Fill the scroll background
+ */
+ void fill();
+
+ /**
+ * Draw a special symbol
+ */
+ void writeSymbol(int symbolId);
+public:
+ ScrollView(const Common::String &name);
+ virtual ~ScrollView() {}
+
+ void draw() override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 59382d7292b..1c4f6c4c50a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -58,9 +58,11 @@ MODULE_OBJS := \
mm1/views/text_entry.o \
mm1/views/text_view.o \
mm1/views_enh/button_container.o \
+ mm1/views_enh/character_info.o \
mm1/views_enh/dialogs.o \
mm1/views_enh/game.o \
mm1/views_enh/map.o \
+ mm1/views_enh/scroll_view.o \
mm1/maps/maps.o \
mm1/maps/map.o \
mm1/maps/map00.o \
Commit: e6b233169a72233ef1f644554f5f08bb29ae3ab6
https://github.com/scummvm/scummvm/commit/e6b233169a72233ef1f644554f5f08bb29ae3ab6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Preparation for displaying text in character info
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/scroll_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index a0f137303a7..b1068fd4b78 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -249,6 +249,32 @@
some_characters: "AVAILABLE CHARACTERS"
not_enough_gold: "*** NOT ENOUGH GOLD ***"
full: "*** BACKPACK FULL ***"
+enhdialogs:
+ character:
+ might: "mgt"
+ intelligence: "int"
+ personality: "Per"
+ endurance: "End"
+ speed: "Spd"
+ accuracy: "Acy"
+ luck: "Luck"
+ age: "Age"
+ level: "Lvl"
+ ac: "AC"
+ hp: "H.P."
+ sp: "S.P."
+ spells: "Spell"
+ condition: "Condition"
+ experience: "Experience"
+ gold: "Gold"
+ gems: "Gems"
+ food: "Food"
+ item: "\x01Item"
+ quick: "\x01Quick"
+ exchange: "\x01Exch"
+ exit: "Exit"
+ conditions:
+ good: "Good"
stats:
none: "NONE"
inventory: "-----<EQUIPPED>----------<BACKPACK>----"
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index b26800f40cc..079fa709e34 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -43,7 +43,7 @@ void TextView::writeChar(char c) {
} else {
Graphics::ManagedSurface s = getSurface();
g_globals->_font.drawChar(&s, c,
- _textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, 0xff);
+ _textPos.x * FONT_SIZE, _textPos.y * FONT_SIZE, _bgColor);
if (++_textPos.x == TEXT_W) {
_textPos.x = 0;
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 2761fa1c40e..5d3342bf01f 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -37,6 +37,14 @@ private:
int _timeoutCtr = 0;
protected:
Common::Point _textPos;
+ byte _bgColor = 0xff;
+
+ /**
+ * Set the text color
+ */
+ void setTextColor(byte col) {
+ _bgColor = col;
+ }
/**
* Write a character
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 00aa081f9f9..e567b79e51d 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -26,8 +26,77 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
+const CharacterInfo::IconPos CharacterInfo::ICONS[CHAR_ICONS_COUNT] = {
+ { 0, 2, 16 },
+ { 2, 2, 39 },
+ { 4, 2, 62 },
+ { 6, 2, 85 },
+ { 8, 2, 108 },
+
+ { 10, 53, 16 },
+ { 12, 53, 39 },
+ { 14, 53, 62 },
+ { 16, 53, 85 },
+ { 18, 53, 108 },
+
+ { 20, 104, 16 },
+ { 22, 104, 39 },
+ { 24, 104, 62 },
+
+ { 30, 169, 16 },
+ { 32, 169, 39 },
+ { 34, 169, 62 },
+ { 36, 169, 85 },
+ { 38, 169, 108 },
+ { 40, 277, 3 },
+ { 42, 277, 35 },
+ { 44, 277, 67 },
+ { 46, 277, 99 }
+};
+
+
CharacterInfo::CharacterInfo() : ScrollView("CharacterInfo") {
_bounds = Common::Rect(0, 0, 320, 146);
+ static const char *FIELDS[CHAR_ICONS_COUNT] = {
+ "might", "intelligence", "personality",
+ "endurance", "speed",
+ "accuracy", "luck", "age", "level", "ac",
+ "hp", "sp", "spells",
+ "experience", "gold", "gems", "food", "condition"
+ };
+
+ for (int i = 0; i < 18; ++i) {
+ ICONS_TEXT[i] = STRING[Common::String::format(
+ "enhdialogs.character.%s", FIELDS[i])].c_str();
+ }
+}
+
+bool CharacterInfo::msgFocus(const FocusMessage &msg) {
+ _viewIcon.load("view.icn");
+ return ScrollView::msgFocus(msg);
+}
+
+bool CharacterInfo::msgUnfocus(const UnfocusMessage &msg) {
+ _viewIcon.clear();
+ return ScrollView::msgUnfocus(msg);
+}
+
+void CharacterInfo::draw() {
+ ScrollView::draw();
+ drawIcons();
+}
+
+void CharacterInfo::drawIcons() {
+ Graphics::ManagedSurface s = getSurface();
+ for (int i = 0; i < CHAR_ICONS_COUNT; ++i) {
+ _viewIcon.draw(&s, ICONS[i]._frame,
+ Common::Point(ICONS[i]._x + FRAME_BORDER_SIZE,
+ ICONS[i]._y + FRAME_BORDER_SIZE));
+ }
+
+ // Write text
+ setTextColor(0);
+ writeString(5, 4, ICONS_TEXT[0]);
}
} // namespace Views
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index d62389a8d74..35393521714 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -23,17 +23,32 @@
#define MM1_VIEWS_ENH_CHARACTER_INFO_H
#include "mm/mm1/views_enh/scroll_view.h"
+#include "mm/xeen/sprites.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
+#define CHAR_ICONS_COUNT 22
+
class CharacterInfo : public ScrollView {
+ struct IconPos {
+ int _frame; int _x; int _y;
+ };
+private:
+ Xeen::SpriteResource _viewIcon;
+ static const IconPos ICONS[CHAR_ICONS_COUNT];
+ const char *ICONS_TEXT[CHAR_ICONS_COUNT];
+
+private:
+ void drawIcons();
public:
CharacterInfo();
virtual ~CharacterInfo() {}
-// void draw() override;
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+ void draw() override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index ff0cf6c852c..3543eaa4613 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -96,7 +96,8 @@ void ScrollView::frame() {
void ScrollView::fill() {
Graphics::ManagedSurface s = getSurface();
- s.fillRect(Common::Rect(8, 8, s.w - 8, s.h - 8), 153);
+ s.fillRect(Common::Rect(FRAME_BORDER_SIZE, FRAME_BORDER_SIZE,
+ s.w - FRAME_BORDER_SIZE, s.h - FRAME_BORDER_SIZE), 153);
}
void ScrollView::writeSymbol(int symbolId) {
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index bcad0264687..c2d8ccb9736 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -28,6 +28,8 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
+#define FRAME_BORDER_SIZE 8
+
class ScrollView : public Views::TextView {
protected:
Common::Point _symbolPos;
Commit: 9f987817f48193a7c96196c9fe5bff44df5f1a07
https://github.com/scummvm/scummvm/commit/9f987817f48193a7c96196c9fe5bff44df5f1a07
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Implement loading of Xeen fonts
Changed paths:
A devtools/create_mm/files/mm1/text_colors.bin
A engines/mm/utils/xeen_font.cpp
A engines/mm/utils/xeen_font.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/text_colors.bin b/devtools/create_mm/files/mm1/text_colors.bin
new file mode 100644
index 00000000000..9881a7ed823
Binary files /dev/null and b/devtools/create_mm/files/mm1/text_colors.bin differ
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index faf6dbd96a8..2468614902a 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -60,11 +60,31 @@ bool Globals::load(bool isEnhanced) {
_globalSprites.load("global.icn");
_tileSprites.load("town.til");
- Common::File f;
- if (!f.open("symbols.bin"))
- error("Could not load symbols.bin");
- f.read(SYMBOLS, 20 * 64);
- f.close();
+ {
+ Common::File f;
+ if (!f.open("symbols.bin"))
+ error("Could not load symbols.bin");
+ f.read(SYMBOLS, 20 * 64);
+ f.close();
+ }
+
+ {
+ Common::File f;
+ if (!f.open("fnt"))
+ error("Could not open font");
+ _fontFixed.load(&f, 0, 0x1000);
+ _fontVariable.load(&f, 0x800, 0x1080);
+ f.close();
+ }
+
+ {
+ Common::File f;
+ if (!f.open("text_colors.bin"))
+ error("Could not open text colors");
+ XeenFont::loadColors(&f);
+ XeenFont::setColors(0);
+ f.close();
+ }
}
return true;
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index eaf6c218f16..6a8fdba9b3e 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -25,6 +25,7 @@
#include "graphics/font.h"
#include "mm/utils/bitmap_font.h"
#include "mm/utils/strings_data.h"
+#include "mm/utils/xeen_font.h"
#include "mm/xeen/sprites.h"
#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/items.h"
@@ -51,6 +52,8 @@ public:
Xeen::SpriteResource _globalSprites;
Xeen::SpriteResource _tileSprites;
byte SYMBOLS[20][64];
+ XeenFont _fontFixed;
+ XeenFont _fontVariable;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 1c4f6c4c50a..ed0c50c6da8 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
utils/bitmap_font.o \
utils/engine_data.o \
utils/strings_data.o \
+ utils/xeen_font.o \
mm1/console.o \
mm1/events.o \
mm1/globals.o \
diff --git a/engines/mm/utils/xeen_font.cpp b/engines/mm/utils/xeen_font.cpp
new file mode 100644
index 00000000000..631825cf4fa
--- /dev/null
+++ b/engines/mm/utils/xeen_font.cpp
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "image/bmp.h"
+#include "mm/utils/xeen_font.h"
+
+namespace MM {
+
+#define FONT_HEIGHT 8
+#define CHARS_COUNT 128
+
+byte XeenFont::_colors[4];
+byte XeenFont::_colorsSet[40][4];
+
+void XeenFont::load(Common::SeekableReadStream *src,
+ size_t charsOffset, size_t charWidthsOffset) {
+ // Read in character data
+ src->seek(charsOffset);
+ _data.resize(CHARS_COUNT * FONT_HEIGHT);
+ for (int i = 0; i < CHARS_COUNT * FONT_HEIGHT; ++i)
+ _data[i] = src->readUint16LE();
+
+ // Read in the char widths
+ src->seek(charWidthsOffset);
+ _widths.resize(128);
+ src->read(&_widths[0], 128);
+}
+
+void XeenFont::loadColors(Common::SeekableReadStream *src) {
+ src->read(_colorsSet, 40 * 4);
+}
+
+void XeenFont::setColors(uint index) {
+ assert(index < 40);
+ Common::copy(&_colorsSet[index][0],
+ &_colorsSet[index][4], &_colors[0]);
+}
+
+int XeenFont::getCharWidth(uint32 chr) const {
+ assert(chr < 128);
+ return _widths[chr];
+}
+
+void XeenFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ assert(chr < 128);
+ if (chr == 'g' || chr == 'p' || chr == 'q' || chr == 'y')
+ ++y;
+
+ const uint16 *src = &_data[chr * 16];
+ for (int yCtr = 0; yCtr < 8; ++yCtr, ++y, ++src) {
+ uint16 srcVal = *src;
+ byte *dest = (byte *)dst->getBasePtr(x, y + yCtr);
+
+ for (int xCtr = 0; xCtr < _widths[chr];
+ ++xCtr, ++dest, srcVal >>= 2) {
+ *dest = _colors[srcVal & 3];
+ }
+ }
+}
+
+} // namespace MM
diff --git a/engines/mm/utils/xeen_font.h b/engines/mm/utils/xeen_font.h
new file mode 100644
index 00000000000..27a0da2bf8f
--- /dev/null
+++ b/engines/mm/utils/xeen_font.h
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_UTILS_XEEN_FONT_H
+#define MM_UTILS_XEEN_FONT_H
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "graphics/font.h"
+#include "graphics/managed_surface.h"
+
+namespace MM {
+
+/**
+ * Implements a font stored as a grid on a passed surface
+ */
+class XeenFont : public Graphics::Font {
+private:
+ Common::Array<uint16> _data;
+ Common::Array<byte> _widths;
+private:
+ static byte _colors[4];
+ static byte _colorsSet[40][4];
+public:
+ static void loadColors(Common::SeekableReadStream *src);
+
+ /**
+ * Set the text colors set index
+ */
+ static void setColors(uint index);
+public:
+ XeenFont() {}
+
+ /**
+ * Loads the font
+ */
+ void load(Common::SeekableReadStream *src,
+ size_t charsOffset, size_t charWidthsOffset);
+
+ /**
+ * Get the font height
+ */
+ int getFontHeight() const override { return 8 + 1; }
+
+ /**
+ * Get the maximum character width
+ */
+ int getMaxCharWidth() const override { return 8; }
+
+ /**
+ * Get the width of the given character
+ */
+ int getCharWidth(uint32 chr) const override;
+
+ /**
+ * Draw a character
+ */
+ void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+ void drawChar(Graphics::ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const override {
+ return Graphics::Font::drawChar(dst, chr, x, y, color);
+ }
+};
+
+} // namespace MM
+
+#endif
Commit: 0a29bed97e35dcbfd7db146ce6bd5b2fd4ab10ae
https://github.com/scummvm/scummvm/commit/0a29bed97e35dcbfd7db146ce6bd5b2fd4ab10ae
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Enhanced mode text rendering working
Changed paths:
A engines/mm/mm1/views_enh/text_view.cpp
A engines/mm/mm1/views_enh/text_view.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/scroll_view.h
engines/mm/module.mk
engines/mm/utils/xeen_font.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 45398e91b53..70f73312bb6 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -194,6 +194,10 @@ void UIElement::draw() {
}
bool UIElement::tick() {
+ if (_timeoutCtr && --_timeoutCtr == 0) {
+ timeout();
+ }
+
for (size_t i = 0; i < _children.size(); ++i) {
if (_children[i]->tick())
return true;
@@ -239,5 +243,13 @@ Graphics::ManagedSurface UIElement::getSurface() const {
return Graphics::ManagedSurface(*g_events->getScreen(), _bounds);
}
+void UIElement::delaySeconds(uint seconds) {
+ _timeoutCtr = seconds * FRAME_RATE;
+}
+
+void UIElement::timeout() {
+ redraw();
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 7bcaf103ccf..006d33e23cb 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -38,6 +38,8 @@ class Events;
class UIElement {
friend class Events;
+private:
+ int _timeoutCtr = 0;
protected:
UIElement *_parent;
Common::Array<UIElement *> _children;
@@ -48,6 +50,17 @@ protected:
Common::Rect getLineBounds(int line1, int line2) const {
return Common::Rect(0, line1 * 8, 320, (line2 + 1) * 8);
}
+
+ /**
+ * Set a delay countdown
+ */
+ void delaySeconds(uint seconds);
+
+ /**
+ * Called when an active timeout countdown expired
+ */
+ virtual void timeout();
+
private:
/**
* Outer method for doing drawing
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index e567b79e51d..199febcb507 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -96,6 +96,7 @@ void CharacterInfo::drawIcons() {
// Write text
setTextColor(0);
+ _textPos = Common::Point(8, 8);
writeString(5, 4, ICONS_TEXT[0]);
}
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index 3543eaa4613..6e503851e3b 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -32,7 +32,7 @@ namespace ViewsEnh {
#define FONT_HEIGHT 8
ScrollView::ScrollView(const Common::String &name) :
- Views::TextView(name, g_engine) {
+ TextView(name, g_engine) {
}
void ScrollView::draw() {
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index c2d8ccb9736..0c6b88569b3 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -22,7 +22,7 @@
#ifndef MM1_VIEWS_ENH_SCROLL_VIEW_H
#define MM1_VIEWS_ENH_SCROLL_VIEW_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views_enh/text_view.h"
namespace MM {
namespace MM1 {
@@ -30,7 +30,7 @@ namespace ViewsEnh {
#define FRAME_BORDER_SIZE 8
-class ScrollView : public Views::TextView {
+class ScrollView : public TextView {
protected:
Common::Point _symbolPos;
protected:
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
new file mode 100644
index 00000000000..fa11c356f18
--- /dev/null
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/globals.h"
+#include "mm/mm1/gfx/gfx.h"
+#include "mm/mm1/views_enh/text_view.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+TextView::TextView(const Common::String &name) :
+ UIElement(name, g_engine) {
+}
+
+TextView::TextView(const Common::String &name, UIElement *owner) :
+ UIElement(name, owner) {
+}
+
+void TextView::setTextColor(byte col) {
+ XeenFont::setColors(col);
+}
+
+void TextView::writeChar(char c) {
+ Graphics::Font &font = _fontVariableWidth ?
+ g_globals->_fontVariable : g_globals->_fontFixed;
+
+ if (c == '\r' || c == '\n') {
+ _textPos.x = 0;
+ _textPos.y++;
+ } else {
+ Graphics::ManagedSurface s = getSurface();
+ font.drawChar(&s, c, _textPos.x, _textPos.y, 0xff);
+
+ _textPos.x += font.getCharWidth(c);
+ if (_textPos.x >= s.w) {
+ _textPos.x = 0;
+ _textPos.y += font.getFontHeight();
+ }
+ }
+}
+
+void TextView::writeChar(int x, int y, char c) {
+ _textPos.x = x;
+ _textPos.y = y;
+ writeChar(c);
+}
+
+void TextView::writeString(const Common::String &str) {
+ for (const unsigned char *s = (const unsigned char *)str.c_str(); *s; ++s) {
+ if (*s & 0x80)
+ warning("TODO: Unknown high-bit set in string character");
+
+ char c = (char)(*s & 0x7f);
+ writeChar(c);
+ }
+}
+
+void TextView::writeString(int x, int y, const Common::String &str) {
+ _textPos.x = x;
+ _textPos.y = y;
+ writeString(str);
+}
+
+void TextView::writeNumber(int val) {
+ writeString(Common::String::format("%d", val));
+}
+
+void TextView::writeNumber(int x, int y, int val) {
+ _textPos.x = x;
+ _textPos.y = y;
+ writeNumber(val);
+}
+
+void TextView::newLine() {
+ _textPos.x = 0;
+ _textPos.y++;
+}
+
+void TextView::clearSurface() {
+ UIElement::clearSurface();
+ _textPos.x = _textPos.y = 0;
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/text_view.h b/engines/mm/mm1/views_enh/text_view.h
new file mode 100644
index 00000000000..11d9781148b
--- /dev/null
+++ b/engines/mm/mm1/views_enh/text_view.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_TEXT_VIEW_H
+#define MM1_VIEWS_ENH_TEXT_VIEW_H
+
+#include "mm/mm1/events.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class TextView : public UIElement {
+protected:
+ Common::Point _textPos;
+ bool _fontVariableWidth = false;
+
+ /**
+ * Set the text color
+ */
+ void setTextColor(byte col);
+
+ /**
+ * Set whether to use fixed width or variable width font
+ */
+ void setProportinateFont(bool flag) {
+ _fontVariableWidth = flag;
+ }
+
+ /**
+ * Write a character
+ */
+ void writeChar(char c);
+ void writeChar(int x, int y, char c);
+
+ /**
+ * Write some text
+ */
+ void writeString(const Common::String &str);
+ void writeString(int x, int y, const Common::String &str);
+
+ /**
+ * Write a number
+ */
+ void writeNumber(int val);
+ void writeNumber(int x, int y, int val);
+
+ /**
+ * Move the text position to the next line
+ */
+ void newLine();
+
+ /**
+ * Clear the surface
+ */
+ void clearSurface() override;
+
+public:
+ TextView(const Common::String &name);
+ TextView(const Common::String &name, UIElement *owner);
+ virtual ~TextView() {}
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index ed0c50c6da8..cd135d03d4b 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -64,6 +64,7 @@ MODULE_OBJS := \
mm1/views_enh/game.o \
mm1/views_enh/map.o \
mm1/views_enh/scroll_view.o \
+ mm1/views_enh/text_view.o \
mm1/maps/maps.o \
mm1/maps/map.o \
mm1/maps/map00.o \
diff --git a/engines/mm/utils/xeen_font.cpp b/engines/mm/utils/xeen_font.cpp
index 631825cf4fa..7cccdd1d71a 100644
--- a/engines/mm/utils/xeen_font.cpp
+++ b/engines/mm/utils/xeen_font.cpp
@@ -65,14 +65,18 @@ void XeenFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32
if (chr == 'g' || chr == 'p' || chr == 'q' || chr == 'y')
++y;
- const uint16 *src = &_data[chr * 16];
- for (int yCtr = 0; yCtr < 8; ++yCtr, ++y, ++src) {
+ const uint16 *src = &_data[chr * FONT_HEIGHT];
+ for (int yCtr = 0; yCtr < FONT_HEIGHT; ++yCtr, ++src) {
+ if ((y + yCtr) < 0 || (y + yCtr) > dst->h)
+ continue;
+
uint16 srcVal = *src;
byte *dest = (byte *)dst->getBasePtr(x, y + yCtr);
for (int xCtr = 0; xCtr < _widths[chr];
++xCtr, ++dest, srcVal >>= 2) {
- *dest = _colors[srcVal & 3];
+ if ((srcVal & 3) && (x + xCtr) >= 0 && (x + xCtr) < dst->w)
+ *dest = _colors[srcVal & 3];
}
}
}
Commit: 0fe56f64bd6dfd61ea54c804726bbe82aa64b49f
https://github.com/scummvm/scummvm/commit/0fe56f64bd6dfd61ea54c804726bbe82aa64b49f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Set up attribute pairs, more of character info display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views/character_base.cpp
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/locations/tavern.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/locations/training.cpp
engines/mm/mm1/views/quick_ref.cpp
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
engines/mm/mm1/views_enh/text_view.cpp
engines/mm/mm1/views_enh/text_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b1068fd4b78..98b334f7ba1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -251,19 +251,19 @@
full: "*** BACKPACK FULL ***"
enhdialogs:
character:
- might: "mgt"
- intelligence: "int"
+ might: "Mgt"
+ intelligence: "Int"
personality: "Per"
endurance: "End"
speed: "Spd"
accuracy: "Acy"
- luck: "Luck"
+ luck: "Luc"
age: "Age"
level: "Lvl"
ac: "AC"
hp: "H.P."
sp: "S.P."
- spells: "Spell"
+ spells: "Spells"
condition: "Condition"
experience: "Experience"
gold: "Gold"
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 50f9e7a6b63..7f1fb704946 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -119,37 +119,30 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_race);
s.syncAsByte(_class);
- s.syncAsByte(_intBase);
- s.syncAsByte(_int);
- s.syncAsByte(_mgtBase);
- s.syncAsByte(_mgt);
- s.syncAsByte(_perBase);
- s.syncAsByte(_per);
- s.syncAsByte(_endBase);
- s.syncAsByte(_end);
- s.syncAsByte(_spdBase);
- s.syncAsByte(_spd);
- s.syncAsByte(_acyBase);
- s.syncAsByte(_acy);
- s.syncAsByte(_lucBase);
- s.syncAsByte(_luc);
-
- s.syncAsByte(_levelBase);
- s.syncAsByte(_level);
- s.syncAsByte(_ageBase);
- s.syncAsByte(_age);
+ _intelligence.synchronize(s);
+ _might.synchronize(s);
+ _personality.synchronize(s);
+ _endurance.synchronize(s);
+ _speed.synchronize(s);
+ _accuracy.synchronize(s);
+ _luck.synchronize(s);
+ _level.synchronize(s);
+ _age.synchronize(s);
+
s.syncAsUint32LE(_exp);
- s.syncAsUint16LE(_sp);
- s.syncAsUint16LE(_spMax);
- s.syncAsByte(_slvlBase);
- s.syncAsByte(_slvl);
+ s.syncAsByte(_sp._base);
+ s.skip(1);
+ s.syncAsByte(_sp._current);
+ s.skip(1);
+ _slvl.synchronize(s);
+
s.syncAsUint16LE(_gems);
s.syncAsUint16LE(_hpBase);
s.syncAsUint16LE(_hp);
s.syncAsUint16LE(_hpMax);
s.syncAsUint16LE(_gold);
s.skip(2);
- s.syncAsByte(_ac);
+ _ac.synchronize(s);
s.syncAsByte(_food);
s.syncAsByte(_condition);
@@ -169,13 +162,13 @@ void Character::clear() {
_alignment = (Alignment)0;
_race = (Race)0;
_class = (CharacterClass)0;
- _int = _mgt = _per = _end = 0;
- _spd = _acy = _luc = 0;
+ _intelligence = _might = _personality = _endurance = 0;
+ _speed = _accuracy = _luck = 0;
_level = 0;
_age = 0;
_exp = 0;
- _sp = _spMax = 0;
- _slvl = _slvlBase = 0;
+ _sp = 0;
+ _slvl = 0;
_gems = 0;
_hpBase = _hp = _hpMax = 0;
_gold = 0;
@@ -221,40 +214,40 @@ Character::TradeResult Character::trade(int whoTo, int itemIndex) {
Character::LevelIncrease Character::increaseLevel() {
- _level = ++_levelBase;
- _age = ++_ageBase;
- if (_ageBase > 220)
- _ageBase = 220;
+ ++_level;
+ ++_age;
+ if (_age._base > 220)
+ _age._base = 220;
_v6c += 2;
int classNum = _class == NONE ? ROBBER : _class;
int newHP = g_engine->getRandomNumber(CLASS_HP_PER_LEVEL[classNum - 1]);
- if (_endBase >= 40)
+ if (_endurance._base >= 40)
newHP += 10;
- else if (_endBase >= 35)
+ else if (_endurance._base >= 35)
newHP += 9;
- else if (_endBase >= 30)
+ else if (_endurance._base >= 30)
newHP += 8;
- else if (_endBase >= 27)
+ else if (_endurance._base >= 27)
newHP += 7;
- else if (_endBase >= 24)
+ else if (_endurance._base >= 24)
newHP += 6;
- else if (_endBase >= 21)
+ else if (_endurance._base >= 21)
newHP += 5;
- else if (_endBase >= 19)
+ else if (_endurance._base >= 19)
newHP += 4;
- else if (_endBase >= 17)
+ else if (_endurance._base >= 17)
newHP += 3;
- else if (_endBase >= 15)
+ else if (_endurance._base >= 15)
newHP += 2;
- else if (_endBase >= 13)
+ else if (_endurance._base >= 13)
newHP += 1;
- else if (_endBase >= 9)
+ else if (_endurance._base >= 9)
newHP += 0;
- else if (_endBase >= 7)
+ else if (_endurance._base >= 7)
newHP = MAX(newHP - 1, 1);
- else if (_endBase >= 5)
+ else if (_endurance._base >= 5)
newHP = MAX(newHP - 2, 1);
else
newHP = MAX(newHP - 3, 1);
@@ -264,28 +257,28 @@ Character::LevelIncrease Character::increaseLevel() {
int gainedSpells = 0;
if (classNum < ARCHER) {
- if (_levelBase < 7)
+ if (_level._base < 7)
gainedSpells = 0;
- else if (_levelBase == 7)
+ else if (_level._base == 7)
gainedSpells = 1;
- else if (_levelBase == 9)
+ else if (_level._base == 9)
gainedSpells = 2;
- else if (_levelBase == 11)
+ else if (_level._base == 11)
gainedSpells = 3;
- else if (_levelBase == 13)
+ else if (_level._base == 13)
gainedSpells = 4;
} else if (classNum < SORCERER) {
- if (_levelBase == 3)
+ if (_level._base == 3)
gainedSpells = 2;
- else if (_levelBase == 5)
+ else if (_level._base == 5)
gainedSpells = 3;
- else if (_levelBase == 7)
+ else if (_level._base == 7)
gainedSpells = 4;
- else if (_levelBase == 9)
+ else if (_level._base == 9)
gainedSpells = 5;
- else if (_levelBase == 11)
+ else if (_level._base == 11)
gainedSpells = 6;
- else if (_levelBase == 13)
+ else if (_level._base == 13)
gainedSpells = 7;
}
@@ -318,48 +311,51 @@ Character::BuyResult Character::buyItem(byte itemId) {
}
void Character::updateAttributes() {
- _int = _intBase;
- _mgt = _mgtBase;
- _per = _perBase;
- _end = _endBase;
- _spd = _spdBase;
- _acy = _acyBase;
- _luc = _lucBase;
- _level = _levelBase;
- _slvl = _slvlBase;
+ _intelligence.reset();
+ _might.reset();
+ _personality.reset();
+ _endurance.reset();
+ _speed.reset();
+ _personality.reset();
+ _endurance.reset();
+ _speed.reset();
+ _accuracy.reset();
+ _luck.reset();
+ _level.reset();
+ _slvl.reset();
}
void Character::updateAC() {
- int ac = _acBase;
+ int ac = _ac._base;
- if (_spd >= 40)
+ if (_speed >= 40)
ac += 9;
- else if (_spd >= 35)
+ else if (_speed >= 35)
ac += 8;
- else if (_spd >= 30)
+ else if (_speed >= 30)
ac += 7;
- else if (_spd >= 25)
+ else if (_speed >= 25)
ac += 6;
- else if (_spd >= 21)
+ else if (_speed >= 21)
ac += 5;
- else if (_spd >= 19)
+ else if (_speed >= 19)
ac += 4;
- else if (_spd >= 17)
+ else if (_speed >= 17)
ac += 3;
- else if (_spd >= 15)
+ else if (_speed >= 15)
ac += 2;
- else if (_spd >= 13)
+ else if (_speed >= 13)
ac += 1;
- else if (_spd >= 9)
+ else if (_speed >= 9)
ac += 0;
- else if (_spd >= 7)
+ else if (_speed >= 7)
ac = MAX(ac - 1, 0);
- else if (_spd >= 5)
+ else if (_speed >= 5)
ac = MAX(ac - 2, 0);
else
ac = MAX(ac - 3, 0);
- _ac = ac;
+ _ac._current = ac;
}
void Character::castSpell(int lvl, int num) {
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 459091a0f89..431560cd780 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -133,6 +133,37 @@ public:
bool hasShield() const { return hasCategory(isShield); }
};
+/**
+ * Attribute pair representing it's base value and the
+ * current temporary value
+ */
+struct AttributePair {
+ uint8 _current = 0;
+ uint8 _base = 0;
+
+ operator uint8() const { return _current; }
+ AttributePair &operator=(byte v) {
+ _base = _current = v;
+ return *this;
+ }
+ AttributePair &operator++() {
+ if (_base < 255)
+ _current = ++_base;
+ return *this;
+ }
+ AttributePair &operator--() {
+ if (_base > 0)
+ _current = --_base;
+ return *this;
+ }
+ void clear() { _current = _base = 0; }
+ void reset() { _current = _base; }
+ void synchronize(Common::Serializer &s) {
+ s.syncAsByte(_base);
+ s.syncAsByte(_current);
+ }
+};
+
struct Character {
char _name[16] = { 0 };
Sex _sex = MALE;
@@ -141,24 +172,24 @@ struct Character {
Race _race = HUMAN;
CharacterClass _class = NONE;
- uint8 _int = 0, _mgt = 0, _per = 0, _end = 0;
- uint8 _spd = 0, _acy = 0, _luc = 0;
- uint8 _intBase = 0, _mgtBase = 0, _perBase = 0;
- uint8 _endBase = 0, _spdBase = 0, _acyBase = 0;
- uint8 _lucBase = 0;
+ AttributePair _intelligence;
+ AttributePair _might;
+ AttributePair _personality;
+ AttributePair _endurance;
+ AttributePair _speed;
+ AttributePair _accuracy;
+ AttributePair _luck;
- uint8 _levelBase = 0;
- uint8 _level = 0;
- uint8 _ageBase = 0;
- uint8 _age = 0;
- uint32 _exp = 0;
- uint16 _sp = 0, _spMax = 0;
- uint8 _slvlBase = 0, _slvl = 0;
+ AttributePair _level;
+ AttributePair _age;
+ AttributePair _sp;
+ AttributePair _slvl;
+ AttributePair _ac;
+ uint32 _exp = 0;
uint16 _gems = 0;
uint16 _hpBase = 0, _hp = 0, _hpMax = 0;
uint32 _gold = 0;
- byte _acBase = 0, _ac = 0;
uint8 _food = 0;
uint8 _condition = 0;
Inventory _equipped;
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 0f10cdec524..d57c8a5e97b 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -275,7 +275,7 @@ void ViewBase::bash() {
uint might = g_engine->getRandomNumber(100);
for (uint i = 0; i < g_globals->_party.size(); ++i)
- might += g_globals->_party[i]._mgt;
+ might += g_globals->_party[i]._might;
might = MIN(might, 255U);
// Check for busting
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 2468614902a..b5b859ed872 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -72,8 +72,8 @@ bool Globals::load(bool isEnhanced) {
Common::File f;
if (!f.open("fnt"))
error("Could not open font");
- _fontFixed.load(&f, 0, 0x1000);
- _fontVariable.load(&f, 0x800, 0x1080);
+ _fontNormal.load(&f, 0, 0x1000);
+ _fontReduced.load(&f, 0x800, 0x1080);
f.close();
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 6a8fdba9b3e..0717114e79f 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -52,8 +52,8 @@ public:
Xeen::SpriteResource _globalSprites;
Xeen::SpriteResource _tileSprites;
byte SYMBOLS[20][64];
- XeenFont _fontFixed;
- XeenFont _fontVariable;
+ XeenFont _fontNormal;
+ XeenFont _fontReduced;
public:
Globals();
virtual ~Globals();
diff --git a/engines/mm/mm1/views/character_base.cpp b/engines/mm/mm1/views/character_base.cpp
index a109fdb9bea..05f3ab4b3f9 100644
--- a/engines/mm/mm1/views/character_base.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -33,7 +33,7 @@ void CharacterBase::printStats() {
newLine();
writeString(STRING["stats.attributes.int"]);
- writeNumber(re._int);
+ writeNumber(re._intelligence);
_textPos.x = 8;
writeString(STRING["stats.attributes.level"]);
writeNumber(re._level);
@@ -46,20 +46,20 @@ void CharacterBase::printStats() {
newLine();
writeString(STRING["stats.attributes.mgt"]);
- writeNumber(re._mgt);
+ writeNumber(re._might);
newLine();
writeString(STRING["stats.attributes.per"]);
- writeNumber(re._per);
+ writeNumber(re._personality);
_textPos.x = 8;
writeString(STRING["stats.attributes.sp"]);
- writeNumber(re._sp);
+ writeNumber(re._sp._current);
_textPos.x = 16;
writeChar('/');
- writeNumber(re._spMax);
+ writeNumber(re._sp._base);
_textPos.x = 22;
writeChar('(');
- writeNumber(re._slvl);
+ writeNumber(re._slvl._current);
writeChar(')');
_textPos.x = 26;
writeString(STRING["stats.attributes.gems"]);
@@ -67,11 +67,11 @@ void CharacterBase::printStats() {
newLine();
writeString(STRING["stats.attributes.end"]);
- writeNumber(re._end);
+ writeNumber(re._endurance);
newLine();
writeString(STRING["stats.attributes.spd"]);
- writeNumber(re._spd);
+ writeNumber(re._speed);
_textPos.x = 8;
writeString(STRING["stats.attributes.hp"]);
writeNumber(re._hp);
@@ -84,11 +84,11 @@ void CharacterBase::printStats() {
newLine();
writeString(STRING["stats.attributes.acy"]);
- writeNumber(re._acy);
+ writeNumber(re._accuracy);
newLine();
writeString(STRING["stats.attributes.luc"]);
- writeNumber(re._luc);
+ writeNumber(re._luck);
_textPos.x = 8;
writeString(STRING["stats.attributes.ac"]);
writeNumber(re._ac);
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index e58911f1ad5..6cda3992718 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -367,7 +367,7 @@ void CharacterInfo::equipItem(uint index) {
break;
case ITEMCAT_ARMOR:
case ITEMCAT_SHIELD:
- c._acBase += item._val17;
+ c._ac._base += item._val17;
break;
default:
break;
@@ -439,7 +439,7 @@ void CharacterInfo::removeItem(uint index) {
break;
case ITEMCAT_ARMOR:
case ITEMCAT_SHIELD:
- c._acBase = MAX((int)c._acBase - (int)item._val17, 0);
+ c._ac._base = MAX((int)c._ac._base - (int)item._val17, 0);
break;
default:
break;
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index e9459cf78fd..c4adc6aaa59 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -72,13 +72,13 @@ void CreateCharacters::NewCharacter::save() {
re._alignment = re._alignmentInitial = _alignment;
re._race = _race;
re._class = _class;
- re._int = _attribs1[INTELLECT];
- re._mgt = _attribs1[MIGHT];
- re._per = _attribs1[PERSONALITY];
- re._end = _attribs1[ENDURANCE];
- re._spd = _attribs1[SPEED];
- re._acy = _attribs1[ACCURACY];
- re._luc = _attribs1[LUCK];
+ re._intelligence = _attribs1[INTELLECT];
+ re._might = _attribs1[MIGHT];
+ re._personality = _attribs1[PERSONALITY];
+ re._endurance = _attribs1[ENDURANCE];
+ re._speed = _attribs1[SPEED];
+ re._accuracy = _attribs1[ACCURACY];
+ re._luck = _attribs1[LUCK];
switch (_class) {
case KNIGHT:
@@ -175,8 +175,8 @@ void CreateCharacters::NewCharacter::setSP(int amount) {
else if (amount >= 13)
level = 1;
- re._sp = re._spMax = level + 3;
- re._slvl = re._slvlBase = 1;
+ re._sp = level + 3;
+ re._slvl = 1;
}
/*------------------------------------------------------------------------*/
diff --git a/engines/mm/mm1/views/locations/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
index 2971d9cf9a1..0fb08d0b352 100644
--- a/engines/mm/mm1/views/locations/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -87,7 +87,7 @@ void Tavern::haveADrink() {
} else if (subtractGold(1)) {
if (++g_globals->_currCharacter->_numDrinks < 3 ||
g_engine->getRandomNumber(10) <
- g_globals->_currCharacter->_end) {
+ g_globals->_currCharacter->_endurance) {
displayMessage(STRING["dialogs.tavern.great_stuff"]);
} else {
if (!(g_globals->_currCharacter->_condition & BAD_CONDITION))
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index f495ee62717..3ad4a706cdf 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -158,9 +158,8 @@ void Temple::restoreHealth() {
c._hpBase = c._hp;
if (_isEradicated) {
- c._age += 10;
- if (c._endBase)
- c._end = --c._endBase;
+ c._age._current += 10;
+ --c._endurance;
}
redraw();
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index 19b512c891e..218b3e2aabe 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -52,7 +52,7 @@ void Training::timeout() {
void Training::checkCharacter() {
Character &c = *g_globals->_currCharacter;
- _currLevel = c._levelBase;
+ _currLevel = c._level._base;
if (_currLevel >= MAX_LEVEL)
return;
@@ -164,7 +164,7 @@ void Training::train() {
clearSurface();
writeString(0, 3, STRING["dialogs.training.congrats"]);
- writeNumber(c._levelBase);
+ writeNumber(c._level._base);
writeString(7, 5, Common::String::format(
STRING["dialogs.training.hp"].c_str(), lvl._numHP));
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 25729ada36a..124e02b7cd2 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -51,7 +51,7 @@ void QuickRef::draw() {
writeNumber(c._sp);
_textPos.x = 32;
writeChar('/');
- writeNumber(c._spMax);
+ writeNumber(c._sp._base);
// AC
_textPos.x = 38;
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 199febcb507..436a53d86c8 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -81,9 +81,33 @@ bool CharacterInfo::msgUnfocus(const UnfocusMessage &msg) {
return ScrollView::msgUnfocus(msg);
}
+bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ return true;
+ }
+
+ return false;
+}
+
void CharacterInfo::draw() {
ScrollView::draw();
+ drawTitle();
drawIcons();
+ drawStats();
+}
+
+void CharacterInfo::drawTitle() {
+ const Character &c = *g_globals->_currCharacter;
+ Common::String msg = Common::String::format(
+ "%s : %s %s %s",
+ c._name,
+ "X",
+ "Y",
+ "Z"
+ );
+
+ writeString(8, 8, msg);
}
void CharacterInfo::drawIcons() {
@@ -93,11 +117,58 @@ void CharacterInfo::drawIcons() {
Common::Point(ICONS[i]._x + FRAME_BORDER_SIZE,
ICONS[i]._y + FRAME_BORDER_SIZE));
}
+}
+
+void CharacterInfo::drawStats() {
+ // Draw stat titles
+ for (int i = 0; i < 18; ++i) {
+ writeString(ICONS[i]._x + 35, ICONS[i]._y + 10,
+ ICONS_TEXT[i]);
+ }
+
+ // Draw stat values
+ const Character &c = *g_globals->_currCharacter;
+ const uint CURR[17] = {
+ c._might._current, c._intelligence._current,
+ c._personality._current, c._endurance._current,
+ c._speed._current, c._accuracy._current,
+ c._luck._current, c._age._base, c._level._current,
+ c._ac._current, c._hp, c._sp._current, 0,
+ c._exp, c._gold, c._gems, c._food
+ };
+ const uint BASE[17] = {
+ c._might._base, c._intelligence._base,
+ c._personality._base, c._endurance._base,
+ c._speed._base, c._accuracy._base,
+ c._luck._base, c._age._base, c._level._base,
+ c._ac._base, c._hp, c._sp._base, 0,
+ c._exp, c._gold, c._gems, c._food
+ };
+
+ for (int i = 0; i < 17; ++i) {
+ if (i == 12)
+ continue;
+
+ Common::Point pt(ICONS[i]._x + 35, ICONS[i]._y + 19);
+ if (i < 10)
+ pt.x += 8 + (CURR[i] < 10 ? 8 : 0);
+
+ setTextColor(statColor(CURR[i], BASE[i]));
+ writeNumber(pt.x, pt.y, CURR[i]);
+ }
+}
- // Write text
- setTextColor(0);
- _textPos = Common::Point(8, 8);
- writeString(5, 4, ICONS_TEXT[0]);
+int CharacterInfo::statColor(int amount, int threshold) {
+ if (amount < 1)
+ return 6;
+ else if (amount > threshold)
+ return 2;
+ else if (amount == threshold)
+ return 15;
+ else if (amount >= (threshold / 4))
+ return 9;
+ else
+ return 32;
}
} // namespace Views
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index 35393521714..7bfe9a2bb0c 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -41,13 +41,17 @@ private:
const char *ICONS_TEXT[CHAR_ICONS_COUNT];
private:
+ void drawTitle();
void drawIcons();
+ void drawStats();
+ int statColor(int amount, int threshold);
public:
CharacterInfo();
virtual ~CharacterInfo() {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
void draw() override;
};
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index fa11c356f18..4005da117b0 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -37,12 +37,13 @@ TextView::TextView(const Common::String &name, UIElement *owner) :
}
void TextView::setTextColor(byte col) {
- XeenFont::setColors(col);
+ _colorsNum = col;
}
void TextView::writeChar(char c) {
- Graphics::Font &font = _fontVariableWidth ?
- g_globals->_fontVariable : g_globals->_fontFixed;
+ XeenFont::setColors(_colorsNum);
+ Graphics::Font &font = _fontReduced ?
+ g_globals->_fontReduced : g_globals->_fontNormal;
if (c == '\r' || c == '\n') {
_textPos.x = 0;
diff --git a/engines/mm/mm1/views_enh/text_view.h b/engines/mm/mm1/views_enh/text_view.h
index 11d9781148b..28d6e80f5bf 100644
--- a/engines/mm/mm1/views_enh/text_view.h
+++ b/engines/mm/mm1/views_enh/text_view.h
@@ -31,7 +31,8 @@ namespace ViewsEnh {
class TextView : public UIElement {
protected:
Common::Point _textPos;
- bool _fontVariableWidth = false;
+ int _colorsNum = 0;
+ bool _fontReduced = false;
/**
* Set the text color
@@ -39,10 +40,10 @@ protected:
void setTextColor(byte col);
/**
- * Set whether to use fixed width or variable width font
+ * Set whether to use the standard large sized font or reduced one
*/
- void setProportinateFont(bool flag) {
- _fontVariableWidth = flag;
+ void setReduced(bool flag) {
+ _fontReduced = flag;
}
/**
Commit: c69cf6cd95686166bf7132627084413fcc4625f9
https://github.com/scummvm/scummvm/commit/c69cf6cd95686166bf7132627084413fcc4625f9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:06:59+01:00
Commit Message:
MM: MM1: Finished title display in enhanced character info view
Changed paths:
A engines/mm/utils/strings.cpp
A engines/mm/utils/strings.h
engines/mm/mm1/console.cpp
engines/mm/mm1/data/char.cpp
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/module.mk
engines/mm/utils/strings_data.cpp
engines/mm/xeen/debugger.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 1fe896c6c19..e439188db13 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -22,6 +22,7 @@
#include "common/file.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "mm/utils/strings.h"
#include "mm/mm1/console.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/events.h"
@@ -29,22 +30,6 @@
namespace MM {
namespace MM1 {
-static int strToInt(const char *s) {
- if (!*s)
- // No string at all
- return 0;
- else if (toupper(s[strlen(s) - 1]) != 'H')
- // Standard decimal string
- return atoi(s);
-
- // Hexadecimal string
- uint tmp = 0;
- int read = sscanf(s, "%xh", &tmp);
- if (read < 1)
- error("strToInt failed on string \"%s\"", s);
- return (int)tmp;
-}
-
Console::Console() : GUI::Debugger() {
registerCmd("dump_map", WRAP_METHOD(Console, cmdDumpMap));
registerCmd("map_string", WRAP_METHOD(Console, cmdMapString));
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index 7f1fb704946..ce8528e8548 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -140,8 +140,15 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsUint16LE(_hpBase);
s.syncAsUint16LE(_hp);
s.syncAsUint16LE(_hpMax);
- s.syncAsUint16LE(_gold);
- s.skip(2);
+
+ // Gold field is annoying by being 3 bytes
+ uint goldLo = _gold & 0xffff;
+ uint goldHi = _gold >> 16;
+ s.syncAsUint16LE(goldLo);
+ s.syncAsByte(goldHi);
+ if (s.isLoading())
+ _gold = goldLo | (goldHi << 16);
+
_ac.synchronize(s);
s.syncAsByte(_food);
s.syncAsByte(_condition);
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 436a53d86c8..e43710a5d1e 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views_enh/character_info.h"
+#include "mm/utils/strings.h"
#include "mm/mm1/globals.h"
namespace MM {
@@ -73,6 +74,9 @@ CharacterInfo::CharacterInfo() : ScrollView("CharacterInfo") {
bool CharacterInfo::msgFocus(const FocusMessage &msg) {
_viewIcon.load("view.icn");
+ MetaEngine::setKeybindingMode(
+ KeybindingMode::KBMODE_PARTY_MENUS);
+
return ScrollView::msgFocus(msg);
}
@@ -90,6 +94,18 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
return false;
}
+bool CharacterInfo::msgAction(const ActionMessage &msg) {
+ if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ g_globals->_currCharacter = &g_globals->_party[
+ msg._action - KEYBIND_VIEW_PARTY1];
+ redraw();
+ return true;
+ }
+
+ return false;
+}
+
void CharacterInfo::draw() {
ScrollView::draw();
drawTitle();
@@ -101,10 +117,10 @@ void CharacterInfo::drawTitle() {
const Character &c = *g_globals->_currCharacter;
Common::String msg = Common::String::format(
"%s : %s %s %s",
- c._name,
- "X",
- "Y",
- "Z"
+ camelCase(c._name).c_str(),
+ capitalize(STRING[Common::String::format("stats.alignments.%d", (int)c._alignment)]).c_str(),
+ capitalize(STRING[Common::String::format("stats.races.%d", (int)c._race)]).c_str(),
+ capitalize(STRING[Common::String::format("stats.classes.%d", (int)c._class)]).c_str()
);
writeString(8, 8, msg);
@@ -141,7 +157,7 @@ void CharacterInfo::drawStats() {
c._personality._base, c._endurance._base,
c._speed._base, c._accuracy._base,
c._luck._base, c._age._base, c._level._base,
- c._ac._base, c._hp, c._sp._base, 0,
+ c._ac._current, c._hp, c._sp._base, 0,
c._exp, c._gold, c._gems, c._food
};
@@ -149,7 +165,7 @@ void CharacterInfo::drawStats() {
if (i == 12)
continue;
- Common::Point pt(ICONS[i]._x + 35, ICONS[i]._y + 19);
+ Common::Point pt(ICONS[i]._x + 35, ICONS[i]._y + 20);
if (i < 10)
pt.x += 8 + (CURR[i] < 10 ? 8 : 0);
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index 7bfe9a2bb0c..f8092aa2a56 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -52,6 +52,7 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
void draw() override;
};
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index 6e503851e3b..302df0b49bc 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -38,6 +38,7 @@ ScrollView::ScrollView(const Common::String &name) :
void ScrollView::draw() {
frame();
fill();
+ setTextColor(0);
}
void ScrollView::frame() {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index cd135d03d4b..0e301ec8bf9 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS := \
meta_engine.o \
utils/bitmap_font.o \
utils/engine_data.o \
+ utils/strings.o \
utils/strings_data.o \
utils/xeen_font.o \
mm1/console.o \
diff --git a/engines/mm/utils/strings.cpp b/engines/mm/utils/strings.cpp
new file mode 100644
index 00000000000..c924ef9dfc0
--- /dev/null
+++ b/engines/mm/utils/strings.cpp
@@ -0,0 +1,93 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/textconsole.h"
+#include "mm/utils/strings.h"
+
+namespace MM {
+
+Common::String capitalize(const Common::String &str) {
+ Common::String result = str;
+ bool capitalize = true;
+
+ for (uint i = 0; i < str.size(); ++i) {
+ if (capitalize) {
+ result.setChar(toupper(result[i]), i);
+ capitalize = false;
+ } else {
+ result.setChar(tolower(result[i]), i);
+ }
+
+ if (result[i] == '.')
+ capitalize = true;
+ }
+
+ return result;
+}
+
+Common::String camelCase(const Common::String &str) {
+ Common::String result = str;
+ bool capitalize = true;
+
+ for (uint i = 0; i < str.size(); ++i) {
+ if (capitalize) {
+ result.setChar(toupper(result[i]), i);
+ capitalize = false;
+ } else {
+ result.setChar(tolower(result[i]), i);
+ }
+
+ if (result[i] == ' ')
+ capitalize = true;
+ }
+
+ return result;
+}
+
+int strToInt(const Common::String &str) {
+ const char *s = str.c_str();
+ size_t size = strlen(s);
+
+ if (size == 0)
+ // No string at all
+ return 0;
+
+ if (toupper(s[size - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+int hexToInt(const Common::String &str) {
+ uint tmp = 0;
+ int read = sscanf(str.c_str(), "%xh", &tmp);
+ if (read < 1)
+ error("hexToInt failed on string \"%s\"", str.c_str());
+ return (int)tmp;
+}
+
+} // namespace MM
diff --git a/engines/mm/utils/strings.h b/engines/mm/utils/strings.h
new file mode 100644
index 00000000000..1dbbcaa99ec
--- /dev/null
+++ b/engines/mm/utils/strings.h
@@ -0,0 +1,36 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM_UTILS_STRINGS_H
+#define MM_UTILS_STRINGS_H
+
+#include "common/str.h"
+
+namespace MM {
+
+extern Common::String capitalize(const Common::String &str);
+extern Common::String camelCase(const Common::String &str);
+extern int strToInt(const Common::String &str);
+extern int hexToInt(const Common::String &str);
+
+} // namespace MM
+
+#endif
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
index 4fc4b25cf0d..d8166f0da14 100644
--- a/engines/mm/utils/strings_data.cpp
+++ b/engines/mm/utils/strings_data.cpp
@@ -22,6 +22,7 @@
#include "common/array.h"
#include "common/file.h"
#include "mm/utils/strings_data.h"
+#include "mm/utils/strings.h"
namespace MM {
@@ -73,11 +74,14 @@ bool StringsData::load(const Common::String &filename) {
value[i + 1] == 'r')) {
value.deleteChar(i);
value.setChar('\n', i);
- } else if (!strncmp(value.c_str() + i, "\\x8B", 4)) {
+ } else if (!strncmp(value.c_str() + i, "\\x", 2)) {
+ Common::String hex(value.c_str() + i + 2,
+ value.c_str() + i + 4);
+
value.deleteChar(i);
value.deleteChar(i);
value.deleteChar(i);
- value.setChar('\x8B', i);
+ value.setChar((char)hexToInt(hex), i);
} else if (value[i] == '"' && value[i + 1] == '"') {
value.deleteChar(i);
}
diff --git a/engines/mm/xeen/debugger.cpp b/engines/mm/xeen/debugger.cpp
index a6123f5ef10..97d5ea49d56 100644
--- a/engines/mm/xeen/debugger.cpp
+++ b/engines/mm/xeen/debugger.cpp
@@ -20,6 +20,7 @@
*/
#include "common/file.h"
+#include "mm/utils/strings.h"
#include "mm/xeen/xeen.h"
#include "mm/xeen/debugger.h"
#include "mm/xeen/files.h"
@@ -27,27 +28,6 @@
namespace MM {
namespace Xeen {
-static int strToInt(const char *s) {
- size_t size = strlen(s);
-
- if (size == 0)
- // No string at all
- return 0;
-
- if (toupper(s[size - 1]) != 'H')
- // Standard decimal string
- return atoi(s);
-
- // Hexadecimal string
- uint tmp = 0;
- int read = sscanf(s, "%xh", &tmp);
- if (read < 1)
- error("strToInt failed on string \"%s\"", s);
- return (int)tmp;
-}
-
-/*------------------------------------------------------------------------*/
-
Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm),
_spellId(-1), _invincible(false), _intangible(false), _superStrength(false) {
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
Commit: 0c1213933969fca83e89338571f3fb8a722958e9
https://github.com/scummvm/scummvm/commit/0c1213933969fca83e89338571f3fb8a722958e9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Display of enhanced char info buttons text
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/text_view.cpp
engines/mm/mm1/views_enh/text_view.h
engines/mm/utils/strings.cpp
engines/mm/utils/strings.h
engines/mm/utils/strings_data.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 98b334f7ba1..7dc1c706bf8 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -269,12 +269,13 @@ enhdialogs:
gold: "Gold"
gems: "Gems"
food: "Food"
- item: "\x01Item"
- quick: "\x01Quick"
- exchange: "\x01Exch"
- exit: "Exit"
+ item: "\x01""37Item"
+ quick: "\x01""37Quick"
+ exchange: "\x01""37Exch"
conditions:
good: "Good"
+ misc:
+ exit: "Exit"
stats:
none: "NONE"
inventory: "-----<EQUIPPED>----------<BACKPACK>----"
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index e43710a5d1e..3aad370c621 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -133,6 +133,12 @@ void CharacterInfo::drawIcons() {
Common::Point(ICONS[i]._x + FRAME_BORDER_SIZE,
ICONS[i]._y + FRAME_BORDER_SIZE));
}
+
+ // Text for buttons
+ writeString(285, 33, STRING["enhdialogs.character.item"]);
+ writeString(282, 65, STRING["enhdialogs.character.quick"]);
+ writeString(284, 98, STRING["enhdialogs.character.exchange"]);
+ writeString(286, 130, STRING["enhdialogs.misc.exit"]);
}
void CharacterInfo::drawStats() {
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 4005da117b0..282d37b7da2 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -36,11 +36,14 @@ TextView::TextView(const Common::String &name, UIElement *owner) :
UIElement(name, owner) {
}
-void TextView::setTextColor(byte col) {
+byte TextView::setTextColor(byte col) {
+ byte oldColor = _colorsNum;
_colorsNum = col;
+ return oldColor;
}
void TextView::writeChar(char c) {
+ assert((unsigned char)c < 0x80);
XeenFont::setColors(_colorsNum);
Graphics::Font &font = _fontReduced ?
g_globals->_fontReduced : g_globals->_fontNormal;
@@ -67,12 +70,20 @@ void TextView::writeChar(int x, int y, char c) {
}
void TextView::writeString(const Common::String &str) {
- for (const unsigned char *s = (const unsigned char *)str.c_str(); *s; ++s) {
- if (*s & 0x80)
- warning("TODO: Unknown high-bit set in string character");
-
- char c = (char)(*s & 0x7f);
- writeChar(c);
+ for (const char *s = (const char *)str.c_str(); *s; ++s) {
+ char c = *s;
+
+ if (c == '\x01') {
+ // Highlight next character for buttons
+ int colNum = atoi(Common::String(s + 1, s + 3).c_str());
+ byte oldCol = setTextColor(colNum);
+ s += 3;
+ writeChar(*s);
+ setTextColor(oldCol);
+
+ } else {
+ writeChar(c);
+ }
}
}
diff --git a/engines/mm/mm1/views_enh/text_view.h b/engines/mm/mm1/views_enh/text_view.h
index 28d6e80f5bf..8ca4ab61190 100644
--- a/engines/mm/mm1/views_enh/text_view.h
+++ b/engines/mm/mm1/views_enh/text_view.h
@@ -37,7 +37,7 @@ protected:
/**
* Set the text color
*/
- void setTextColor(byte col);
+ byte setTextColor(byte col);
/**
* Set whether to use the standard large sized font or reduced one
diff --git a/engines/mm/utils/strings.cpp b/engines/mm/utils/strings.cpp
index c924ef9dfc0..201c8b6e479 100644
--- a/engines/mm/utils/strings.cpp
+++ b/engines/mm/utils/strings.cpp
@@ -62,6 +62,25 @@ Common::String camelCase(const Common::String &str) {
return result;
}
+Common::String searchAndReplace(const Common::String &str,
+ const Common::String &find, const Common::String &replace) {
+ Common::String result = str;
+ const char *p = result.c_str();
+
+ while ((p = strstr(p, find.c_str())) != nullptr) {
+ uint idx = p - result.c_str();
+ result = Common::String::format("%s%s%s",
+ Common::String(result.c_str(), p).c_str(),
+ replace.c_str(),
+ Common::String(p + find.size()).c_str()
+ );
+
+ p = result.c_str() + idx + replace.size();
+ }
+
+ return result;
+}
+
int strToInt(const Common::String &str) {
const char *s = str.c_str();
size_t size = strlen(s);
diff --git a/engines/mm/utils/strings.h b/engines/mm/utils/strings.h
index 1dbbcaa99ec..f39b734322a 100644
--- a/engines/mm/utils/strings.h
+++ b/engines/mm/utils/strings.h
@@ -28,6 +28,8 @@ namespace MM {
extern Common::String capitalize(const Common::String &str);
extern Common::String camelCase(const Common::String &str);
+extern Common::String searchAndReplace(const Common::String &str,
+ const Common::String &find, const Common::String &replace);
extern int strToInt(const Common::String &str);
extern int hexToInt(const Common::String &str);
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
index d8166f0da14..cf35207629c 100644
--- a/engines/mm/utils/strings_data.cpp
+++ b/engines/mm/utils/strings_data.cpp
@@ -66,6 +66,7 @@ bool StringsData::load(const Common::String &filename) {
if (value.hasPrefix("\"") && value.hasSuffix("\"")) {
value.deleteChar(0);
value.deleteLastChar();
+ value = searchAndReplace(value, "\"\"", "");
}
// Replace any sequences
Commit: 90bb192ce1d19b9725109bae5191bb0d795f4dd0
https://github.com/scummvm/scummvm/commit/90bb192ce1d19b9725109bae5191bb0d795f4dd0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Added days suffix to food in char info
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/character_info.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 7dc1c706bf8..dc4132bb3a3 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -269,6 +269,8 @@ enhdialogs:
gold: "Gold"
gems: "Gems"
food: "Food"
+ days: "Days"
+ day: "Day"
item: "\x01""37Item"
quick: "\x01""37Quick"
exchange: "\x01""37Exch"
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 3aad370c621..b11c59c946d 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -150,21 +150,21 @@ void CharacterInfo::drawStats() {
// Draw stat values
const Character &c = *g_globals->_currCharacter;
- const uint CURR[17] = {
+ const uint CURR[16] = {
c._might._current, c._intelligence._current,
c._personality._current, c._endurance._current,
c._speed._current, c._accuracy._current,
c._luck._current, c._age._base, c._level._current,
c._ac._current, c._hp, c._sp._current, 0,
- c._exp, c._gold, c._gems, c._food
+ c._exp, c._gold, c._gems
};
- const uint BASE[17] = {
+ const uint BASE[16] = {
c._might._base, c._intelligence._base,
c._personality._base, c._endurance._base,
c._speed._base, c._accuracy._base,
c._luck._base, c._age._base, c._level._base,
c._ac._current, c._hp, c._sp._base, 0,
- c._exp, c._gold, c._gems, c._food
+ c._exp, c._gold, c._gems
};
for (int i = 0; i < 17; ++i) {
@@ -176,7 +176,18 @@ void CharacterInfo::drawStats() {
pt.x += 8 + (CURR[i] < 10 ? 8 : 0);
setTextColor(statColor(CURR[i], BASE[i]));
- writeNumber(pt.x, pt.y, CURR[i]);
+
+ if (i == 16) {
+ // Food
+ Common::String str = Common::String::format("%d %s",
+ c._food,
+ STRING[c._food == 1 ? "enhdialogs.character.day" :
+ "enhdialogs.character.days"].c_str());
+ setTextColor(15);
+ writeString(pt.x, pt.y, str);
+ } else {
+ writeNumber(pt.x, pt.y, CURR[i]);
+ }
}
}
Commit: d1350f54dce2cd0fdea1a44c50317a2c48d76c02
https://github.com/scummvm/scummvm/commit/d1350f54dce2cd0fdea1a44c50317a2c48d76c02
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Added condition text to char info
Changed paths:
engines/mm/mm1/data/char.cpp
engines/mm/mm1/data/char.h
engines/mm/mm1/views/character_base.cpp
engines/mm/mm1/views_enh/character_info.cpp
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/char.cpp
index ce8528e8548..623cb054c0c 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/char.cpp
@@ -365,6 +365,44 @@ void Character::updateAC() {
_ac._current = ac;
}
+Common::String Character::getConditionString() const {
+ Common::String result;
+ int cond = _condition;
+
+ if (cond == 0) {
+ result += STRING["stats.conditions.good"];
+ } else if (cond == ERADICATED) {
+ result += STRING["stats.conditions.eradicated"];
+ } else {
+ if (cond & BAD_CONDITION) {
+ // Fatal conditions
+ if (cond & DEAD)
+ result += STRING["stats.conditions.dead"];
+ if (cond & STONE)
+ result += STRING["stats.conditions.stone"];
+ } else {
+ if (cond & UNCONSCIOUS)
+ result += STRING["stats.conditions.unconscious"];
+ if (cond & PARALYZED)
+ result += STRING["stats.conditions.paralyzed"];
+ if (cond & POISONED)
+ result += STRING["stats.conditions.poisoned"];
+ if (cond & DISEASED)
+ result += STRING["stats.conditions.diseased"];
+ if (cond & SILENCED)
+ result += STRING["stats.conditions.silenced"];
+ if (cond & BLINDED)
+ result += STRING["stats.conditions.blinded"];
+ if (cond & ASLEEP)
+ result += STRING["stats.conditions.asleep"];
+ }
+
+ result.deleteLastChar();
+ }
+
+ return result;
+}
+
void Character::castSpell(int lvl, int num) {
int lvlNum;
int setNum = _class == ARCHER || _class == SORCERER ? 1 : 0;
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/char.h
index 431560cd780..46645349281 100644
--- a/engines/mm/mm1/data/char.h
+++ b/engines/mm/mm1/data/char.h
@@ -261,6 +261,11 @@ struct Character {
* Cast a spell
*/
void castSpell(int lvl, int num);
+
+ /**
+ * Gets a character's condition string
+ */
+ Common::String getConditionString() const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/character_base.cpp b/engines/mm/mm1/views/character_base.cpp
index 05f3ab4b3f9..63ae8fd22e7 100644
--- a/engines/mm/mm1/views/character_base.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -129,42 +129,11 @@ void CharacterBase::printSummary() {
}
void CharacterBase::printCondition() {
- Character &re = *g_globals->_currCharacter;
+ Character &c = *g_globals->_currCharacter;
writeString(STRING["stats.attributes.cond"]);
_textPos.x++;
- int cond = re._condition;
-
- if (cond == 0) {
- writeString(STRING["stats.conditions.good"]);
- } else if (cond == ERADICATED) {
- writeString(STRING["stats.conditions.eradicated"]);
- } else {
- if (cond & BAD_CONDITION) {
- // Fatal conditions
- if (cond & DEAD)
- writeString(STRING["stats.conditions.dead"]);
- if (cond & STONE)
- writeString(STRING["stats.conditions.stone"]);
- } else {
- if (cond & UNCONSCIOUS)
- writeString(STRING["stats.conditions.unconscious"]);
- if (cond & PARALYZED)
- writeString(STRING["stats.conditions.paralyzed"]);
- if (cond & POISONED)
- writeString(STRING["stats.conditions.poisoned"]);
- if (cond & DISEASED)
- writeString(STRING["stats.conditions.diseased"]);
- if (cond & SILENCED)
- writeString(STRING["stats.conditions.silenced"]);
- if (cond & BLINDED)
- writeString(STRING["stats.conditions.blinded"]);
- if (cond & ASLEEP)
- writeString(STRING["stats.conditions.asleep"]);
- }
-
- --_textPos.x;
- writeChar(' ');
- }
+
+ writeString(c.getConditionString());
}
void CharacterBase::printInventory() {
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index b11c59c946d..235eae3dd55 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -189,6 +189,10 @@ void CharacterInfo::drawStats() {
writeNumber(pt.x, pt.y, CURR[i]);
}
}
+
+ // Condition string
+ setTextColor(15);
+ writeString(204, 128, camelCase(c.getConditionString()));
}
int CharacterInfo::statColor(int amount, int threshold) {
Commit: 12d69ae38574d79a95312517ae32f50bbf830f05
https://github.com/scummvm/scummvm/commit/12d69ae38574d79a95312517ae32f50bbf830f05
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Different text colors for conditions
Changed paths:
engines/mm/mm1/views_enh/character_info.cpp
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 235eae3dd55..a2f7b999bd8 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -191,8 +191,17 @@ void CharacterInfo::drawStats() {
}
// Condition string
- setTextColor(15);
- writeString(204, 128, camelCase(c.getConditionString()));
+ Common::String condStr = camelCase(c.getConditionString());
+ setTextColor(!c._condition ? 15 : 19);
+
+ uint i = condStr.findFirstOf(',');
+ if (i != Common::String::npos) {
+ // More than one condition
+ condStr = Common::String(condStr.c_str(), i);
+ setTextColor(32);
+ }
+
+ writeString(204, 128, condStr);
}
int CharacterInfo::statColor(int amount, int threshold) {
Commit: c8f260ed038759291696d2a2583c1791bac2c70e
https://github.com/scummvm/scummvm/commit/c8f260ed038759291696d2a2583c1791bac2c70e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Skeleton encounter view class
Changed paths:
A engines/mm/mm1/views/encounter.cpp
A engines/mm/mm1/views/encounter.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 1cd578248e4..d2a1fc00fa1 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -25,6 +25,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/create_characters.h"
+#include "mm/mm1/views/encounter.h"
#include "mm/mm1/views/game.h"
#include "mm/mm1/views/main_menu.h"
#include "mm/mm1/views/order.h"
@@ -33,6 +34,7 @@
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/characters.h"
+#include "mm/mm1/views/encounter.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/views/locations/market.h"
@@ -49,6 +51,7 @@ struct Dialogs {
private:
Views::AreYouReady _areYouReady;
Views::CreateCharacters _createCharacters;
+ Views::Encounter _encounter;
Views::Game _game;
Views::MainMenu _mainMenu;
Views::Order _order;
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
new file mode 100644
index 00000000000..bdf05c07a3d
--- /dev/null
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -0,0 +1,39 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/encounter.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Encounter::Encounter() : TextView("Encounter") {
+}
+
+void Encounter::draw() {
+ clearSurface();
+ writeString(10, 10, "Encounter");
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
new file mode 100644
index 00000000000..23c91b21945
--- /dev/null
+++ b/engines/mm/mm1/views/encounter.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENCOUNTER_H
+#define MM1_VIEWS_ENCOUNTER_H
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Encounter : public TextView {
+public:
+ Encounter();
+ virtual ~Encounter() {}
+
+ void draw() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 0e301ec8bf9..15b3d548fe6 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -46,6 +46,7 @@ MODULE_OBJS := \
mm1/views/character_manage.o \
mm1/views/characters.o \
mm1/views/create_characters.o \
+ mm1/views/encounter.o \
mm1/views/game.o \
mm1/views/game_commands.o \
mm1/views/game_messages.o \
Commit: c6afc8b9bd15e33d9cb38ffe793122424eb8c26c
https://github.com/scummvm/scummvm/commit/c6afc8b9bd15e33d9cb38ffe793122424eb8c26c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Added blinking cursor to char info stats
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 70f73312bb6..9f2696473d2 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -247,6 +247,10 @@ void UIElement::delaySeconds(uint seconds) {
_timeoutCtr = seconds * FRAME_RATE;
}
+void UIElement::delayFrames(uint frames) {
+ _timeoutCtr = frames;
+}
+
void UIElement::timeout() {
redraw();
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 006d33e23cb..cc43c29e67b 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -52,10 +52,15 @@ protected:
}
/**
- * Set a delay countdown
+ * Set a delay countdown in seconds
*/
void delaySeconds(uint seconds);
+ /**
+ * Set a delay countdown in frames
+ */
+ void delayFrames(uint frames);
+
/**
* Called when an active timeout countdown expired
*/
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index a2f7b999bd8..37491786180 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -27,6 +27,11 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
+#define CURSOR_BLINK_FRAMES 6
+#define ICONS_COUNT 18
+#define REDUCED_TO_EXPANDED(IDX) ((IDX >= 13) ? IDX + 2 : IDX)
+#define EXPANDED_TO_REDUCED(IDX) ((IDX >= 13) ? IDX - 2 : IDX)
+
const CharacterInfo::IconPos CharacterInfo::ICONS[CHAR_ICONS_COUNT] = {
{ 0, 2, 16 },
{ 2, 2, 39 },
@@ -66,7 +71,7 @@ CharacterInfo::CharacterInfo() : ScrollView("CharacterInfo") {
"experience", "gold", "gems", "food", "condition"
};
- for (int i = 0; i < 18; ++i) {
+ for (int i = 0; i < ICONS_COUNT; ++i) {
ICONS_TEXT[i] = STRING[Common::String::format(
"enhdialogs.character.%s", FIELDS[i])].c_str();
}
@@ -77,6 +82,10 @@ bool CharacterInfo::msgFocus(const FocusMessage &msg) {
MetaEngine::setKeybindingMode(
KeybindingMode::KBMODE_PARTY_MENUS);
+ _cursorCell = 0;
+ showCursor(true);
+ delayFrames(CURSOR_BLINK_FRAMES);
+
return ScrollView::msgFocus(msg);
}
@@ -86,9 +95,46 @@ bool CharacterInfo::msgUnfocus(const UnfocusMessage &msg) {
}
bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ int idx;
+
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
close();
return true;
+ case Common::KEYCODE_UP:
+ showCursor(false);
+ if (--_cursorCell < 0)
+ _cursorCell = ICONS_COUNT - 1;
+ showCursor(true);
+ break;
+ case Common::KEYCODE_DOWN:
+ showCursor(false);
+ if (++_cursorCell >= ICONS_COUNT)
+ _cursorCell = 0;
+ showCursor(true);
+ break;
+ case Common::KEYCODE_LEFT:
+ showCursor(false);
+ idx = REDUCED_TO_EXPANDED(_cursorCell) - 5;
+ if (idx == 13 || idx == 14)
+ idx -= 5;
+ if (idx < 0)
+ idx += 20;
+ _cursorCell = EXPANDED_TO_REDUCED(idx);
+ showCursor(true);
+ break;
+ case Common::KEYCODE_RIGHT:
+ showCursor(false);
+ idx = REDUCED_TO_EXPANDED(_cursorCell) + 5;
+ if (idx == 13 || idx == 14)
+ idx += 5;
+ if (idx >= 20)
+ idx -= 20;
+ _cursorCell = EXPANDED_TO_REDUCED(idx);
+ showCursor(true);
+ break;
+ default:
+ break;
}
return false;
@@ -217,6 +263,27 @@ int CharacterInfo::statColor(int amount, int threshold) {
return 32;
}
+void CharacterInfo::showCursor(bool flag) {
+ const int CURSOR_X[4] = { 9, 60, 111, 176 };
+ const int CURSOR_Y[5] = { 23, 46, 69, 92, 115 };
+
+ if (flag == _cursorVisible)
+ return;
+
+ int idx = REDUCED_TO_EXPANDED(_cursorCell);
+ _cursorVisible = flag;
+
+ Graphics::ManagedSurface s = getSurface();
+ _viewIcon.draw(&s, flag ? 49 : 48,
+ Common::Point(CURSOR_X[idx / 5], CURSOR_Y[idx % 5]));
+ s.markAllDirty();
+}
+
+void CharacterInfo::timeout() {
+ showCursor(!_cursorVisible);
+ delayFrames(CURSOR_BLINK_FRAMES);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index f8092aa2a56..3c33d1cd310 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -39,12 +39,23 @@ private:
Xeen::SpriteResource _viewIcon;
static const IconPos ICONS[CHAR_ICONS_COUNT];
const char *ICONS_TEXT[CHAR_ICONS_COUNT];
+ int _cursorCell = 0;
+ bool _cursorVisible = false;
private:
void drawTitle();
void drawIcons();
void drawStats();
int statColor(int amount, int threshold);
+
+ /**
+ * Toggle display of cursor
+ */
+ void showCursor(bool flag);
+
+protected:
+ void timeout() override;
+
public:
CharacterInfo();
virtual ~CharacterInfo() {}
Commit: 283c1669d917a74d20e37e4a4427f2844e00e4cb
https://github.com/scummvm/scummvm/commit/283c1669d917a74d20e37e4a4427f2844e00e4cb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Adding support for scroll views to display text
Changed paths:
A engines/mm/mm1/views_enh/scroll_text.cpp
A engines/mm/mm1/views_enh/scroll_text.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.h
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/scroll_view.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index dc4132bb3a3..34bd646f3fe 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -251,26 +251,45 @@
full: "*** BACKPACK FULL ***"
enhdialogs:
character:
- might: "Mgt"
- intelligence: "Int"
- personality: "Per"
- endurance: "End"
- speed: "Spd"
- accuracy: "Acy"
- luck: "Luc"
- age: "Age"
- level: "Lvl"
- ac: "AC"
- hp: "H.P."
- sp: "S.P."
- spells: "Spells"
- condition: "Condition"
- experience: "Experience"
- gold: "Gold"
- gems: "Gems"
- food: "Food"
- days: "Days"
- day: "Day"
+ stats:
+ might: "Mgt"
+ intelligence: "Int"
+ personality: "Per"
+ endurance: "End"
+ speed: "Spd"
+ accuracy: "Acy"
+ luck: "Luc"
+ age: "Age"
+ level: "Lvl"
+ ac: "AC"
+ hp: "H.P."
+ sp: "S.P."
+ spells: "Spells"
+ condition: "Condition"
+ experience: "Experience"
+ gold: "Gold"
+ gems: "Gems"
+ food: "Food"
+ days: "Days"
+ day: "Day"
+ long:
+ might: "Might"
+ intelligence: "Intelligence"
+ personality: "Personality"
+ endurance: "Endurance"
+ speed: "Speed"
+ accuracy: "Accuracy"
+ luck: "Luck"
+ age: "Age"
+ level: "Level"
+ ac: "Armor Class"
+ hp: "Hit Points"
+ sp: "Spell Points"
+ spells: "Active Spells"
+ current: "Current:"
+ next_level: "Next Level:"
+ eligible: "Eligible"
+ ineligible: "Ineligible"
item: "\x01""37Item"
quick: "\x01""37Quick"
exchange: "\x01""37Exch"
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index cc43c29e67b..ae2757cbd94 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -118,7 +118,7 @@ public:
/**
* Sets the element's bounds
*/
- void setBounds(const Common::Rect &r) {
+ virtual void setBounds(const Common::Rect &r) {
_bounds = r;
}
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 37491786180..d08f265c4d7 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -73,7 +73,7 @@ CharacterInfo::CharacterInfo() : ScrollView("CharacterInfo") {
for (int i = 0; i < ICONS_COUNT; ++i) {
ICONS_TEXT[i] = STRING[Common::String::format(
- "enhdialogs.character.%s", FIELDS[i])].c_str();
+ "enhdialogs.character.stats.%s", FIELDS[i])].c_str();
}
}
@@ -227,8 +227,8 @@ void CharacterInfo::drawStats() {
// Food
Common::String str = Common::String::format("%d %s",
c._food,
- STRING[c._food == 1 ? "enhdialogs.character.day" :
- "enhdialogs.character.days"].c_str());
+ STRING[c._food == 1 ? "enhdialogs.character.stats.day" :
+ "enhdialogs.character.stats.days"].c_str());
setTextColor(15);
writeString(pt.x, pt.y, str);
} else {
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
new file mode 100644
index 00000000000..d462ef5af0c
--- /dev/null
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -0,0 +1,72 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/scroll_text.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+#define FONT_HEIGHT 8
+
+ScrollText::ScrollText() {
+ _font = &g_globals->_fontNormal;
+}
+
+void ScrollText::setSize(int w, int h) {
+ _size.x = w;
+ _size.y = h;
+ _rowCount = h / 8;
+}
+
+void ScrollText::setReduced(bool flag) {
+ _font = flag ? &g_globals->_fontReduced :
+ &g_globals->_fontReduced;
+}
+
+void ScrollText::addLine(const Common::String &str,
+ TextAlignment align, byte color) {
+ if (_lines.size() < _rowCount) {
+ Common::Point pt(0, _lines.size() * 8);
+
+ if (align != ALIGN_LEFT) {
+ size_t strWidth = _font->getStringWidth(str);
+ if (align == ALIGN_RIGHT)
+ pt.x = _size.x - strWidth;
+ else
+ pt.x = (_size.x - strWidth) / 2;
+ }
+
+ _lines.push_back(Line(str, pt, color));
+ }
+}
+
+void ScrollText::addText(const Common::String &str,
+ int lineNum, byte color, int xp) {
+ _lines.push_back(Line(str,
+ Common::Point(xp, lineNum * FONT_HEIGHT), color));
+}
+
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
new file mode 100644
index 00000000000..11329a9a9d2
--- /dev/null
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -0,0 +1,97 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_SCROLL_TEXT_H
+#define MM1_VIEWS_ENH_SCROLL_TEXT_H
+
+#include "common/rect.h"
+#include "common/str.h"
+#include "graphics/font.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+enum TextAlignment {
+ ALIGN_LEFT, ALIGN_RIGHT, ALIGN_MIDDLE
+};
+
+class ScrollText {
+ struct Line {
+ Common::String _str;
+ Common::Point _pos;
+ byte _color = 0;
+
+ Line(const Common::String &str,
+ const Common::Point &pos, byte color = 0) :
+ _str(str), _pos(pos), _color(color) {
+ }
+ };
+public:
+ typedef Common::Array<Line> Lines;
+private:
+ Graphics::Font *_font;
+ Common::Point _size;
+ size_t _rowCount = 0;
+ Lines _lines;
+public:
+ ScrollText();
+
+ /**
+ * Sets the size for the text area
+ */
+ void setSize(int w, int h);
+
+ Lines::iterator begin() { return _lines.begin(); }
+ Lines::iterator end() { return _lines.end(); }
+ Lines::const_iterator begin() const { return _lines.begin(); }
+ Lines::const_iterator end() const { return _lines.end(); }
+
+ /**
+ * Sets the font mode
+ */
+ void setReduced(bool flag);
+
+ /**
+ * Clear the lines
+ */
+ void clear() {
+ _lines.clear();
+ }
+
+ /**
+ * Simplest form that adds lines one at a time
+ */
+ void addLine(const Common::String &str,
+ TextAlignment align = ALIGN_LEFT, byte color = 0);
+
+ /**
+ * Add a new line fragment for a given position
+ */
+ void addText(const Common::String &str,
+ int lineNum, byte color = 0, int xp = 0);
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index 302df0b49bc..bd4bfc488e4 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -28,22 +28,39 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
-#define FONT_WIDTH 8
-#define FONT_HEIGHT 8
+#define SYMBOL_WIDTH FRAME_BORDER_SIZE
+#define SYMBOL_HEIGHT FRAME_BORDER_SIZE
ScrollView::ScrollView(const Common::String &name) :
TextView(name, g_engine) {
}
+void ScrollView::setBounds(const Common::Rect &r) {
+ _bounds = r;
+ Common::Rect inner = r;
+ inner.grow(-FRAME_BORDER_SIZE);
+ _text.setSize(r.width(), r.height());
+}
+
void ScrollView::draw() {
frame();
fill();
setTextColor(0);
+
+ // Iterate through displaying any text
+ for (ScrollText::Lines::const_iterator i = _text.begin();
+ i != _text.end(); ++i) {
+ setTextColor(i->_color);
+ writeString(i->_pos.x + FRAME_BORDER_SIZE,
+ i->_pos.y + FRAME_BORDER_SIZE,
+ i->_str
+ );
+ }
}
void ScrollView::frame() {
- int xCount = (_bounds.width() - 9) / FONT_WIDTH;
- int yCount = (_bounds.height() - 9) / FONT_HEIGHT;
+ int xCount = (_bounds.width() - 9) / SYMBOL_WIDTH;
+ int yCount = (_bounds.height() - 9) / SYMBOL_HEIGHT;
// Write the top line
_symbolPos = Common::Point(0, 0);
@@ -58,19 +75,19 @@ void ScrollView::frame() {
}
}
- _symbolPos.x = _bounds.width() - FONT_WIDTH;
+ _symbolPos.x = _bounds.width() - SYMBOL_WIDTH;
writeSymbol(5);
// Write the vertical edges
if (yCount > 0) {
int symbolId = 6;
for (int i = 0; i < yCount; ++i) {
- _symbolPos.y += FONT_HEIGHT;
+ _symbolPos.y += SYMBOL_HEIGHT;
_symbolPos.x = 0;
writeSymbol(symbolId);
- _symbolPos.x = _bounds.width() - FONT_WIDTH;
+ _symbolPos.x = _bounds.width() - SYMBOL_WIDTH;
writeSymbol(symbolId + 4);
if (++symbolId == 10)
@@ -79,7 +96,7 @@ void ScrollView::frame() {
}
// Write the bottom line
- _symbolPos = Common::Point(0, _bounds.height() - FONT_HEIGHT);
+ _symbolPos = Common::Point(0, _bounds.height() - SYMBOL_HEIGHT);
writeSymbol(14);
if (xCount > 0) {
@@ -91,7 +108,7 @@ void ScrollView::frame() {
}
}
- _symbolPos.x = _bounds.width() - FONT_WIDTH;
+ _symbolPos.x = _bounds.width() - SYMBOL_WIDTH;
writeSymbol(19);
}
@@ -105,20 +122,20 @@ void ScrollView::writeSymbol(int symbolId) {
Graphics::ManagedSurface s = getSurface();
const byte *srcP = &g_globals->SYMBOLS[symbolId][0];
s.addDirtyRect(Common::Rect(_symbolPos.x, _symbolPos.y,
- _symbolPos.x + FONT_WIDTH, _symbolPos.y + FONT_HEIGHT));
+ _symbolPos.x + SYMBOL_WIDTH, _symbolPos.y + SYMBOL_HEIGHT));
- for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
+ for (int yp = 0; yp < SYMBOL_HEIGHT; ++yp) {
byte *destP = (byte *)s.getBasePtr(
_symbolPos.x, _symbolPos.y + yp);
- for (int xp = 0; xp < FONT_WIDTH; ++xp, ++destP) {
+ for (int xp = 0; xp < SYMBOL_WIDTH; ++xp, ++destP) {
byte b = *srcP++;
if (b)
*destP = b;
}
}
- _symbolPos.x += FONT_WIDTH;
+ _symbolPos.x += SYMBOL_WIDTH;
}
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index 0c6b88569b3..65b694476d3 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -23,6 +23,7 @@
#define MM1_VIEWS_ENH_SCROLL_VIEW_H
#include "mm/mm1/views_enh/text_view.h"
+#include "mm/mm1/views_enh/scroll_text.h"
namespace MM {
namespace MM1 {
@@ -33,6 +34,7 @@ namespace ViewsEnh {
class ScrollView : public TextView {
protected:
Common::Point _symbolPos;
+ ScrollText _text;
protected:
/**
* Draw the scroll frame
@@ -52,7 +54,38 @@ public:
ScrollView(const Common::String &name);
virtual ~ScrollView() {}
+ /**
+ * Sets the element's bounds
+ */
+ void setBounds(const Common::Rect &r) override;
+
+ /**
+ * Draw the view
+ */
void draw() override;
+
+ /**
+ * Clear text lines
+ */
+ void clearText() {
+ _text.clear();
+ }
+
+ /**
+ * Simplest form that adds lines one at a time
+ */
+ void addLine(const Common::String &str,
+ TextAlignment align = ALIGN_LEFT, byte color = 0) {
+ _text.addLine(str, align, color);
+ }
+
+ /**
+ * Add a new line fragment for a given position
+ */
+ void addText(const Common::String &str,
+ int lineNum, byte color = 0, int xp = 0) {
+ _text.addText(str, lineNum, color, xp);
+ }
};
} // namespace ViewsEnh
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 15b3d548fe6..89360bdb835 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -65,6 +65,7 @@ MODULE_OBJS := \
mm1/views_enh/dialogs.o \
mm1/views_enh/game.o \
mm1/views_enh/map.o \
+ mm1/views_enh/scroll_text.o \
mm1/views_enh/scroll_view.o \
mm1/views_enh/text_view.o \
mm1/maps/maps.o \
Commit: 0a08b72e04aa75496161fe7828580c5e22c22ca1
https://github.com/scummvm/scummvm/commit/0a08b72e04aa75496161fe7828580c5e22c22ca1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:00+01:00
Commit Message:
MM: MM1: Making text display it's own scroll subclass
Changed paths:
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/scroll_view.h
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index d08f265c4d7..410e8ddcd7d 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -284,6 +284,18 @@ void CharacterInfo::timeout() {
delayFrames(CURSOR_BLINK_FRAMES);
}
+void CharacterInfo::showAttribute(int attrNum) {
+ // Switch the cursor to the selected attribute
+ showCursor(false);
+ _cursorCell = attrNum;
+ showCursor(true);
+
+ getSurface().markAllDirty();
+ g_events->getScreen()->update();
+
+ // Display the info dialog
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index 3c33d1cd310..a2396c899b9 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -43,9 +43,24 @@ private:
bool _cursorVisible = false;
private:
+ /**
+ * Draw the title text
+ */
void drawTitle();
+
+ /**
+ * Draw the icons
+ */
void drawIcons();
+
+ /**
+ * Draw the stats
+ */
void drawStats();
+
+ /**
+ * Return the color for a given stat
+ */
int statColor(int amount, int threshold);
/**
@@ -53,6 +68,11 @@ private:
*/
void showCursor(bool flag);
+ /**
+ * Show the details of a given attribute
+ */
+ void showAttribute(int attrNum);
+
protected:
void timeout() override;
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index d462ef5af0c..d882c2b1509 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -28,14 +28,15 @@ namespace ViewsEnh {
#define FONT_HEIGHT 8
-ScrollText::ScrollText() {
+ScrollText::ScrollText() : ScrollView("ScrollText") {
_font = &g_globals->_fontNormal;
}
-void ScrollText::setSize(int w, int h) {
- _size.x = w;
- _size.y = h;
- _rowCount = h / 8;
+void ScrollText::setBounds(const Common::Rect &r) {
+ ScrollView::setBounds(_bounds);
+ _innerBounds = _bounds;
+ _innerBounds.grow(-FRAME_BORDER_SIZE);
+ _rowCount = _innerBounds.height() / FONT_HEIGHT;
}
void ScrollText::setReduced(bool flag) {
@@ -51,9 +52,10 @@ void ScrollText::addLine(const Common::String &str,
if (align != ALIGN_LEFT) {
size_t strWidth = _font->getStringWidth(str);
if (align == ALIGN_RIGHT)
- pt.x = _size.x - strWidth;
+ pt.x = _innerBounds.right - strWidth;
else
- pt.x = (_size.x - strWidth) / 2;
+ pt.x = _innerBounds.left +
+ (_innerBounds.width() + strWidth) / 2;
}
_lines.push_back(Line(str, pt, color));
@@ -66,6 +68,28 @@ void ScrollText::addText(const Common::String &str,
Common::Point(xp, lineNum * FONT_HEIGHT), color));
}
+void ScrollText::draw() {
+ ScrollView::draw();
+
+ // Iterate through displaying any text
+ for (Lines::const_iterator i = begin();
+ i != end(); ++i) {
+ setTextColor(i->_color);
+ writeString(i->_pos.x + FRAME_BORDER_SIZE,
+ i->_pos.y + FRAME_BORDER_SIZE,
+ i->_str
+ );
+ }
+}
+
+bool ScrollText::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ return true;
+ }
+
+ return false;
+}
} // namespace ViewsEnh
} // namespace MM1
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index 11329a9a9d2..a94955d4879 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -25,6 +25,7 @@
#include "common/rect.h"
#include "common/str.h"
#include "graphics/font.h"
+#include "mm/mm1/views_enh/scroll_view.h"
namespace MM {
namespace MM1 {
@@ -34,7 +35,10 @@ enum TextAlignment {
ALIGN_LEFT, ALIGN_RIGHT, ALIGN_MIDDLE
};
-class ScrollText {
+/**
+ * Derived scroll class for displaying static text
+ */
+class ScrollText : public ScrollView {
struct Line {
Common::String _str;
Common::Point _pos;
@@ -49,16 +53,16 @@ public:
typedef Common::Array<Line> Lines;
private:
Graphics::Font *_font;
- Common::Point _size;
size_t _rowCount = 0;
Lines _lines;
+ Common::Rect _innerBounds;
public:
ScrollText();
/**
- * Sets the size for the text area
+ * Sets the element's bounds
*/
- void setSize(int w, int h);
+ void setBounds(const Common::Rect &r) override;
Lines::iterator begin() { return _lines.begin(); }
Lines::iterator end() { return _lines.end(); }
@@ -88,6 +92,16 @@ public:
*/
void addText(const Common::String &str,
int lineNum, byte color = 0, int xp = 0);
+
+ /**
+ * Draw the view
+ */
+ void draw() override;
+
+ /**
+ * Handle keypress events
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index bd4bfc488e4..947f82f1d52 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -35,27 +35,10 @@ ScrollView::ScrollView(const Common::String &name) :
TextView(name, g_engine) {
}
-void ScrollView::setBounds(const Common::Rect &r) {
- _bounds = r;
- Common::Rect inner = r;
- inner.grow(-FRAME_BORDER_SIZE);
- _text.setSize(r.width(), r.height());
-}
-
void ScrollView::draw() {
frame();
fill();
setTextColor(0);
-
- // Iterate through displaying any text
- for (ScrollText::Lines::const_iterator i = _text.begin();
- i != _text.end(); ++i) {
- setTextColor(i->_color);
- writeString(i->_pos.x + FRAME_BORDER_SIZE,
- i->_pos.y + FRAME_BORDER_SIZE,
- i->_str
- );
- }
}
void ScrollView::frame() {
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index 65b694476d3..72f73f3fa94 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -23,7 +23,6 @@
#define MM1_VIEWS_ENH_SCROLL_VIEW_H
#include "mm/mm1/views_enh/text_view.h"
-#include "mm/mm1/views_enh/scroll_text.h"
namespace MM {
namespace MM1 {
@@ -34,7 +33,6 @@ namespace ViewsEnh {
class ScrollView : public TextView {
protected:
Common::Point _symbolPos;
- ScrollText _text;
protected:
/**
* Draw the scroll frame
@@ -54,38 +52,10 @@ public:
ScrollView(const Common::String &name);
virtual ~ScrollView() {}
- /**
- * Sets the element's bounds
- */
- void setBounds(const Common::Rect &r) override;
-
/**
* Draw the view
*/
void draw() override;
-
- /**
- * Clear text lines
- */
- void clearText() {
- _text.clear();
- }
-
- /**
- * Simplest form that adds lines one at a time
- */
- void addLine(const Common::String &str,
- TextAlignment align = ALIGN_LEFT, byte color = 0) {
- _text.addLine(str, align, color);
- }
-
- /**
- * Add a new line fragment for a given position
- */
- void addText(const Common::String &str,
- int lineNum, byte color = 0, int xp = 0) {
- _text.addText(str, lineNum, color, xp);
- }
};
} // namespace ViewsEnh
Commit: 392b4ff847171b6df6a4433cb16291c7213bd2ba
https://github.com/scummvm/scummvm/commit/392b4ff847171b6df6a4433cb16291c7213bd2ba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:01+01:00
Commit Message:
MM: MM1: Basic stat popups now showing
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
engines/mm/mm1/views_enh/text_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 34bd646f3fe..2004cac0dde 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -273,6 +273,8 @@ enhdialogs:
days: "Days"
day: "Day"
long:
+ current: "Current"
+ base: "Base"
might: "Might"
intelligence: "Intelligence"
personality: "Personality"
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 410e8ddcd7d..7dce26e615f 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -63,6 +63,8 @@ const CharacterInfo::IconPos CharacterInfo::ICONS[CHAR_ICONS_COUNT] = {
CharacterInfo::CharacterInfo() : ScrollView("CharacterInfo") {
_bounds = Common::Rect(0, 0, 320, 146);
+ _statInfo.setReduced(true);
+
static const char *FIELDS[CHAR_ICONS_COUNT] = {
"might", "intelligence", "personality",
"endurance", "speed",
@@ -133,11 +135,14 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
_cursorCell = EXPANDED_TO_REDUCED(idx);
showCursor(true);
break;
+ case Common::KEYCODE_RETURN:
+ showAttribute(_cursorCell);
+ break;
default:
break;
}
- return false;
+ return true;
}
bool CharacterInfo::msgAction(const ActionMessage &msg) {
@@ -294,6 +299,166 @@ void CharacterInfo::showAttribute(int attrNum) {
g_events->getScreen()->update();
// Display the info dialog
+ const int STAT_POS[2][20] = {
+ {
+ 61, 61, 61, 61, 61, 112, 112, 112, 112, 112,
+ 177, 177, 177, 177, 177, 34, 34, 34, 34, 34
+ }, {
+ 24, 47, 70, 93, 116, 24, 47, 70, 93, 116,
+ 24, 47, 70, 93, 116, 24, 47, 70, 93, 116
+ }
+ };
+
+ int attrib = REDUCED_TO_EXPANDED(attrNum);
+ assert(attrib < 20);
+
+ Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib],
+ STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52);
+ _statInfo.setBounds(bounds);
+
+ const Character &c = *g_globals->_currCharacter;
+ const uint CURR[12] = {
+ c._might._current, c._intelligence._current,
+ c._personality._current, c._endurance._current,
+ c._speed._current, c._accuracy._current,
+ c._luck._current, c._age._base, c._level._current,
+ c._ac._current, c._hp, c._sp._current
+ };
+ const uint BASE[12] = {
+ c._might._base, c._intelligence._base,
+ c._personality._base, c._endurance._base,
+ c._speed._base, c._accuracy._base,
+ c._luck._base, c._age._base, c._level._base,
+ c._ac._current, c._hp, c._sp._base
+ };
+ const char *TITLES[12] = {
+ "might", "intelligence", "personality",
+ "endurance", "speed", "accuracy", "luck",
+ "age", "level", "ac", "hp", "sp"
+ };
+
+ if (attrib < 12) {
+ _statInfo.clear();
+ _statInfo.addLine(
+ STRING[Common::String::format("enhdialogs.character.long.%s",
+ TITLES[attrib]).c_str()],
+ ALIGN_MIDDLE);
+
+ int xc = (bounds.width() - FRAME_BORDER_SIZE * 2) / 2;
+ _statInfo.addText(STRING["enhdialogs.character.long.current"],
+ 1, 0, ALIGN_RIGHT, xc - 8);
+ _statInfo.addText("/", 1, 0, ALIGN_MIDDLE);
+ _statInfo.addText(STRING["enhdialogs.character.long.base"],
+ 1, 0, ALIGN_LEFT, xc + 8);
+
+ _statInfo.addText(Common::String::format("%u", CURR[attrib]),
+ 2, 0, ALIGN_RIGHT, xc - 8);
+ _statInfo.addText("/", 2, 0, ALIGN_MIDDLE);
+ _statInfo.addText(Common::String::format("%u", BASE[attrib]),
+ 2, 0, ALIGN_LEFT, xc + 8);
+ }
+
+ /*
+ case 15:
+ // Experience
+ stat1 = c.getCurrentExperience();
+ stat2 = c.experienceToNextLevel();
+ msg = Common::String::format(Res.EXPERIENCE_TEXT,
+ Res.STAT_NAMES[attrib], stat1,
+ stat2 == 0 ? Res.ELIGIBLE : Common::String::format("%d", stat2).c_str()
+ );
+ bounds.setHeight(43);
+ break;
+
+ case 16:
+ // Gold
+ msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[0],
+ party._gold, party._bankGold);
+ bounds.setHeight(43);
+ break;
+
+ case 17:
+ // Gems
+ msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[1],
+ party._gems, party._bankGems);
+ bounds.setHeight(43);
+ break;
+
+ case 18:
+ {
+ // Food
+ int food = (party._food / party._activeParty.size()) / 3;
+ msg = Common::String::format(Res.FOOD_TEXT, Res.CONSUMABLE_NAMES[2],
+ party._food, getFoodOnHandPlurals(food), food, getDaysPlurals(food));
+ break;
+ }
+
+ case 19:
+ {
+ // Conditions
+ Common::String lines[20];
+ const char **_tmpConditions = c._sex == FEMALE ? (const char **)Res.CONDITION_NAMES_F : (const char **)Res.CONDITION_NAMES_M;
+ int total = 0;
+ for (int condition = CURSED; condition <= ERADICATED; ++condition) {
+ if (c._conditions[condition]) {
+ if (condition >= UNCONSCIOUS) {
+ lines[condition] = Common::String::format("\n\t020%s",
+ _tmpConditions[condition]);
+ } else {
+ lines[condition] = Common::String::format("\n\t020%s\t095-%d",
+ _tmpConditions[condition], c._conditions[condition]);
+ }
+
+ ++total;
+ }
+ }
+
+ Condition condition = c.worstCondition();
+ if (condition == NO_CONDITION) {
+ lines[0] = Common::String::format("\n\t020%s", Res.GOOD);
+ ++total;
+ }
+
+ if (party._blessed) {
+ lines[16] = Common::String::format(Res.BLESSED, party._blessed);
+ ++total;
+ }
+ if (party._powerShield) {
+ lines[17] = Common::String::format(Res.POWER_SHIELD, party._powerShield);
+ ++total;
+ }
+ if (party._holyBonus) {
+ lines[18] = Common::String::format(Res.HOLY_BONUS, party._holyBonus);
+ ++total;
+ }
+ if (party._heroism) {
+ lines[19] = Common::String::format(Res.HEROISM, party._heroism);
+ ++total;
+ }
+
+ msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1",
+ Res.CONSUMABLE_NAMES[3], lines[0].c_str(), lines[1].c_str(),
+ lines[2].c_str(), lines[3].c_str(), lines[4].c_str(),
+ lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
+ lines[8].c_str(), lines[9].c_str(), lines[10].c_str(),
+ lines[11].c_str(), lines[12].c_str(), lines[13].c_str(),
+ lines[14].c_str(), lines[15].c_str(), lines[16].c_str(),
+ lines[17].c_str(), lines[18].c_str(), lines[19].c_str()
+ );
+
+ bounds.top -= ((total - 1) / 2) * 8;
+ bounds.setHeight(total * 9 + 26);
+ if (bounds.bottom >= SCREEN_HEIGHT)
+ bounds.moveTo(bounds.left, SCREEN_HEIGHT - bounds.height() - 1);
+ break;
+ }
+
+ default:
+ break;
+ }
+ */
+
+ _statInfo.addView();
}
} // namespace Views
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index a2396c899b9..ffbf8a90f66 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -23,6 +23,7 @@
#define MM1_VIEWS_ENH_CHARACTER_INFO_H
#include "mm/mm1/views_enh/scroll_view.h"
+#include "mm/mm1/views_enh/scroll_text.h"
#include "mm/xeen/sprites.h"
namespace MM {
@@ -41,7 +42,7 @@ private:
const char *ICONS_TEXT[CHAR_ICONS_COUNT];
int _cursorCell = 0;
bool _cursorVisible = false;
-
+ ScrollText _statInfo;
private:
/**
* Draw the title text
@@ -71,7 +72,7 @@ private:
/**
* Show the details of a given attribute
*/
- void showAttribute(int attrNum);
+ void showAttribute(int attrib);
protected:
void timeout() override;
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index d882c2b1509..d89a84e3f39 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -29,43 +29,55 @@ namespace ViewsEnh {
#define FONT_HEIGHT 8
ScrollText::ScrollText() : ScrollView("ScrollText") {
- _font = &g_globals->_fontNormal;
}
void ScrollText::setBounds(const Common::Rect &r) {
- ScrollView::setBounds(_bounds);
- _innerBounds = _bounds;
+ ScrollView::setBounds(r);
+ _innerBounds = r;
_innerBounds.grow(-FRAME_BORDER_SIZE);
_rowCount = _innerBounds.height() / FONT_HEIGHT;
}
-void ScrollText::setReduced(bool flag) {
- _font = flag ? &g_globals->_fontReduced :
- &g_globals->_fontReduced;
-}
-
void ScrollText::addLine(const Common::String &str,
TextAlignment align, byte color) {
if (_lines.size() < _rowCount) {
- Common::Point pt(0, _lines.size() * 8);
-
- if (align != ALIGN_LEFT) {
- size_t strWidth = _font->getStringWidth(str);
- if (align == ALIGN_RIGHT)
- pt.x = _innerBounds.right - strWidth;
- else
- pt.x = _innerBounds.left +
- (_innerBounds.width() + strWidth) / 2;
+ switch (align) {
+ case ALIGN_LEFT:
+ addText(str, _lines.size(), color, align);
+ break;
+ case ALIGN_RIGHT:
+ addText(str, _lines.size(), color, align);
+ break;
+ case ALIGN_MIDDLE:
+ addText(str, _lines.size(), color, align);
+ break;
}
-
- _lines.push_back(Line(str, pt, color));
}
}
void ScrollText::addText(const Common::String &str,
- int lineNum, byte color, int xp) {
- _lines.push_back(Line(str,
- Common::Point(xp, lineNum * FONT_HEIGHT), color));
+ int lineNum, byte color, TextAlignment align, int xp) {
+ Common::Point pt(xp, lineNum * 8);
+ Graphics::Font &font = _fontReduced ?
+ g_globals->_fontReduced : g_globals->_fontNormal;
+
+ if (align != ALIGN_LEFT) {
+ size_t strWidth = font.getStringWidth(str);
+
+ if (align == ALIGN_RIGHT) {
+ // Right alignment
+ if (xp == 0)
+ xp = _innerBounds.width();
+ pt.x = xp - strWidth;
+ } else {
+ // Middle alignment
+ if (xp == 0)
+ xp = _innerBounds.width() / 2;
+ pt.x = xp - strWidth / 2;
+ }
+ }
+
+ _lines.push_back(Line(str, pt, color));
}
void ScrollText::draw() {
@@ -76,9 +88,7 @@ void ScrollText::draw() {
i != end(); ++i) {
setTextColor(i->_color);
writeString(i->_pos.x + FRAME_BORDER_SIZE,
- i->_pos.y + FRAME_BORDER_SIZE,
- i->_str
- );
+ i->_pos.y + FRAME_BORDER_SIZE, i->_str);
}
}
@@ -91,6 +101,11 @@ bool ScrollText::msgKeypress(const KeypressMessage &msg) {
return false;
}
+bool ScrollText::msgMouseUp(const MouseUpMessage &msg) {
+ close();
+ return true;
+}
+
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index a94955d4879..15b6009efae 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -52,7 +52,6 @@ class ScrollText : public ScrollView {
public:
typedef Common::Array<Line> Lines;
private:
- Graphics::Font *_font;
size_t _rowCount = 0;
Lines _lines;
Common::Rect _innerBounds;
@@ -69,11 +68,6 @@ public:
Lines::const_iterator begin() const { return _lines.begin(); }
Lines::const_iterator end() const { return _lines.end(); }
- /**
- * Sets the font mode
- */
- void setReduced(bool flag);
-
/**
* Clear the lines
*/
@@ -91,7 +85,8 @@ public:
* Add a new line fragment for a given position
*/
void addText(const Common::String &str,
- int lineNum, byte color = 0, int xp = 0);
+ int lineNum, byte color = 0,
+ TextAlignment align = ALIGN_LEFT, int xp = 0);
/**
* Draw the view
@@ -102,6 +97,11 @@ public:
* Handle keypress events
*/
bool msgKeypress(const KeypressMessage &msg) override;
+
+ /**
+ * Handle mouse clicks
+ */
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/text_view.h b/engines/mm/mm1/views_enh/text_view.h
index 8ca4ab61190..b3c4fcb8e12 100644
--- a/engines/mm/mm1/views_enh/text_view.h
+++ b/engines/mm/mm1/views_enh/text_view.h
@@ -39,13 +39,6 @@ protected:
*/
byte setTextColor(byte col);
- /**
- * Set whether to use the standard large sized font or reduced one
- */
- void setReduced(bool flag) {
- _fontReduced = flag;
- }
-
/**
* Write a character
*/
@@ -78,6 +71,13 @@ public:
TextView(const Common::String &name);
TextView(const Common::String &name, UIElement *owner);
virtual ~TextView() {}
+
+ /**
+ * Set whether to use the standard large sized font or reduced one
+ */
+ void setReduced(bool flag) {
+ _fontReduced = flag;
+ }
};
} // namespace ViewsEnh
Commit: 66e73672a81ea40b70cd8f504405e6627f02c691
https://github.com/scummvm/scummvm/commit/66e73672a81ea40b70cd8f504405e6627f02c691
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:01+01:00
Commit Message:
MM: MM1: Show stat info by clicking on icons
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 2004cac0dde..f9908bcf003 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -288,8 +288,7 @@ enhdialogs:
hp: "Hit Points"
sp: "Spell Points"
spells: "Active Spells"
- current: "Current:"
- next_level: "Next Level:"
+ next_level: "Next Level"
eligible: "Eligible"
ineligible: "Ineligible"
item: "\x01""37Item"
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 7dce26e615f..bee6ce9f338 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -157,6 +157,20 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
return false;
}
+bool CharacterInfo::msgMouseUp(const MouseUpMessage &msg) {
+ // Check if a stat icon was clicked
+ Common::Rect r(16, 16);
+ for (int i = 0; i < ICONS_COUNT; ++i) {
+ r.moveTo(ICONS[i]._x + 8, ICONS[i]._y + 8);
+ if (r.contains(msg._pos)) {
+ showAttribute(i);
+ return true;
+ }
+ }
+
+ return ScrollView::msgMouseUp(msg);
+}
+
void CharacterInfo::draw() {
ScrollView::draw();
drawTitle();
@@ -304,8 +318,8 @@ void CharacterInfo::showAttribute(int attrNum) {
61, 61, 61, 61, 61, 112, 112, 112, 112, 112,
177, 177, 177, 177, 177, 34, 34, 34, 34, 34
}, {
- 24, 47, 70, 93, 116, 24, 47, 70, 93, 116,
- 24, 47, 70, 93, 116, 24, 47, 70, 93, 116
+ 24, 47, 70, 93, 93, 24, 47, 70, 93, 93,
+ 24, 47, 70, 93, 93, 24, 47, 70, 93, 93
}
};
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index ffbf8a90f66..2980d23d0fd 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -85,6 +85,7 @@ public:
bool msgUnfocus(const UnfocusMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
void draw() override;
};
Commit: 6ad30c9094f813f6ec6c0536f8db187f02f16a70
https://github.com/scummvm/scummvm/commit/6ad30c9094f813f6ec6c0536f8db187f02f16a70
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:01+01:00
Commit Message:
MM: MM1: Stat info for gold, gems, food
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/text_view.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index f9908bcf003..019e37e8705 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -291,6 +291,7 @@ enhdialogs:
next_level: "Next Level"
eligible: "Eligible"
ineligible: "Ineligible"
+ on_hand: "on hand"
item: "\x01""37Item"
quick: "\x01""37Quick"
exchange: "\x01""37Exch"
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index bee6ce9f338..167734752f3 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -327,8 +327,9 @@ void CharacterInfo::showAttribute(int attrNum) {
assert(attrib < 20);
Common::Rect bounds(STAT_POS[0][attrib], STAT_POS[1][attrib],
- STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 52);
+ STAT_POS[0][attrib] + 143, STAT_POS[1][attrib] + 44);
_statInfo.setBounds(bounds);
+ _statInfo.clear();
const Character &c = *g_globals->_currCharacter;
const uint CURR[12] = {
@@ -352,7 +353,6 @@ void CharacterInfo::showAttribute(int attrNum) {
};
if (attrib < 12) {
- _statInfo.clear();
_statInfo.addLine(
STRING[Common::String::format("enhdialogs.character.long.%s",
TITLES[attrib]).c_str()],
@@ -370,6 +370,24 @@ void CharacterInfo::showAttribute(int attrNum) {
_statInfo.addText("/", 2, 0, ALIGN_MIDDLE);
_statInfo.addText(Common::String::format("%u", BASE[attrib]),
2, 0, ALIGN_LEFT, xc + 8);
+ } else if (attrib >= 16 && attrib <= 18) {
+ bounds.bottom -= 8;
+ _statInfo.setBounds(bounds);
+
+ uint value = c._gold;
+ Common::String title = STRING["enhdialogs.character.stats.gold"];
+ if (attrib == 17) {
+ value = c._gems;
+ title = STRING["enhdialogs.character.stats.gems"];
+ } else if (attrib == 18) {
+ value = c._food;
+ title = STRING["enhdialogs.character.stats.food"];
+ }
+
+ _statInfo.addLine(title, ALIGN_MIDDLE);
+ _statInfo.addLine(Common::String::format("%u %s",
+ value, STRING["enhdialogs.character.long.on_hand"].c_str()),
+ ALIGN_MIDDLE);
}
/*
@@ -384,29 +402,6 @@ void CharacterInfo::showAttribute(int attrNum) {
bounds.setHeight(43);
break;
- case 16:
- // Gold
- msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[0],
- party._gold, party._bankGold);
- bounds.setHeight(43);
- break;
-
- case 17:
- // Gems
- msg = Common::String::format(Res.IN_PARTY_IN_BANK, Res.CONSUMABLE_NAMES[1],
- party._gems, party._bankGems);
- bounds.setHeight(43);
- break;
-
- case 18:
- {
- // Food
- int food = (party._food / party._activeParty.size()) / 3;
- msg = Common::String::format(Res.FOOD_TEXT, Res.CONSUMABLE_NAMES[2],
- party._food, getFoodOnHandPlurals(food), food, getDaysPlurals(food));
- break;
- }
-
case 19:
{
// Conditions
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 282d37b7da2..98952dcdcaf 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -53,7 +53,8 @@ void TextView::writeChar(char c) {
_textPos.y++;
} else {
Graphics::ManagedSurface s = getSurface();
- font.drawChar(&s, c, _textPos.x, _textPos.y, 0xff);
+ if (c != ' ')
+ font.drawChar(&s, c, _textPos.x, _textPos.y, 0xff);
_textPos.x += font.getCharWidth(c);
if (_textPos.x >= s.w) {
Commit: 5e8ce9f6cb1f3aef212b07b41007bc6d83e91b9c
https://github.com/scummvm/scummvm/commit/5e8ce9f6cb1f3aef212b07b41007bc6d83e91b9c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:01+01:00
Commit Message:
MM: MM1: Message display in enhanced mode
Changed paths:
A engines/mm/mm1/views_enh/game_messages.cpp
A engines/mm/mm1/views_enh/game_messages.h
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/game.cpp
engines/mm/mm1/views_enh/game.h
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/scroll_view.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 167734752f3..da032871c87 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -61,7 +61,8 @@ const CharacterInfo::IconPos CharacterInfo::ICONS[CHAR_ICONS_COUNT] = {
};
-CharacterInfo::CharacterInfo() : ScrollView("CharacterInfo") {
+CharacterInfo::CharacterInfo() :
+ ScrollView("CharacterInfo"), _statInfo("ScrollText") {
_bounds = Common::Rect(0, 0, 320, 146);
_statInfo.setReduced(true);
diff --git a/engines/mm/mm1/views_enh/game.cpp b/engines/mm/mm1/views_enh/game.cpp
index 4e6d4d993dd..15753389c50 100644
--- a/engines/mm/mm1/views_enh/game.cpp
+++ b/engines/mm/mm1/views_enh/game.cpp
@@ -29,7 +29,9 @@ namespace MM1 {
namespace ViewsEnh {
Game::Game() : TextView("Game"),
- _view(this), _commands(this) {
+ _view(this),
+ _commands(this),
+ _messages(this) {
_view.setBounds(Common::Rect(8, 15, 224, 130));
// Load the Xeen background
diff --git a/engines/mm/mm1/views_enh/game.h b/engines/mm/mm1/views_enh/game.h
index 60fe5369777..ab16a7175f6 100644
--- a/engines/mm/mm1/views_enh/game.h
+++ b/engines/mm/mm1/views_enh/game.h
@@ -26,6 +26,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/game_view.h"
#include "mm/mm1/views_enh/game_commands.h"
+#include "mm/mm1/views_enh/game_messages.h"
namespace MM {
namespace MM1 {
@@ -36,6 +37,7 @@ private:
Graphics::ManagedSurface _bg;
Views::GameView _view;
GameCommands _commands;
+ GameMessages _messages;
public:
Game();
virtual ~Game() {}
diff --git a/engines/mm/mm1/views_enh/game_messages.cpp b/engines/mm/mm1/views_enh/game_messages.cpp
new file mode 100644
index 00000000000..ba67fefad79
--- /dev/null
+++ b/engines/mm/mm1/views_enh/game_messages.cpp
@@ -0,0 +1,88 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/util.h"
+#include "mm/utils/strings.h"
+#include "mm/mm1/views_enh/game_messages.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+GameMessages::GameMessages(UIElement *owner) :
+ ScrollText("GameMessages", owner) {
+}
+
+void GameMessages::draw() {
+ // Only draw non-focused messages for a single turn
+ if (_show || g_events->focusedView() == this) {
+ ScrollText::draw();
+ _show = false;
+ }
+}
+
+bool GameMessages::msgInfo(const InfoMessage &msg) {
+ if (msg._ynCallback || msg._keyCallback) {
+ // Do a first draw to show 3d view at new position
+ g_events->redraw();
+ g_events->drawElements();
+
+ addView(this);
+ }
+
+ setBounds(Common::Rect(0, 18 * 8, 234, 200));
+
+ _show = true;
+ _ynCallback = msg._ynCallback;
+ _keyCallback = msg._keyCallback;
+
+ // Process the lines
+ clear();
+ for (auto line : msg._lines) {
+ Common::String str = capitalize(line._text);
+ addText(str, line.y, 0, ALIGN_LEFT, line.x * 8);
+ }
+
+ redraw();
+ return true;
+}
+
+bool GameMessages::msgKeypress(const KeypressMessage &msg) {
+ if (g_events->focusedView() == this) {
+ if (_keyCallback) {
+ _keyCallback(msg);
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ } else if (msg.keycode == Common::KEYCODE_y) {
+ close();
+ _ynCallback();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/game_messages.h b/engines/mm/mm1/views_enh/game_messages.h
new file mode 100644
index 00000000000..7b4a07f3e8e
--- /dev/null
+++ b/engines/mm/mm1/views_enh/game_messages.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_GAME_MESSAGES_H
+#define MM1_VIEWS_ENH_GAME_MESSAGES_H
+
+#include "mm/mm1/messages.h"
+#include "mm/mm1/views_enh/scroll_text.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class GameMessages : public ScrollText {
+private:
+ bool _show = false;
+ YNCallback _ynCallback = nullptr;
+ KeyCallback _keyCallback = nullptr;
+public:
+ GameMessages(UIElement *owner);
+ virtual ~GameMessages() {}
+
+ void draw() override;
+ bool msgInfo(const InfoMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index d89a84e3f39..86ddc920315 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -28,7 +28,12 @@ namespace ViewsEnh {
#define FONT_HEIGHT 8
-ScrollText::ScrollText() : ScrollView("ScrollText") {
+ScrollText::ScrollText(const Common::String &name) :
+ ScrollView(name) {
+}
+
+ScrollText::ScrollText(const Common::String &name, UIElement *owner) :
+ ScrollView(name, owner) {
}
void ScrollText::setBounds(const Common::Rect &r) {
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index 15b6009efae..e78503d6c82 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -56,7 +56,8 @@ private:
Lines _lines;
Common::Rect _innerBounds;
public:
- ScrollText();
+ ScrollText(const Common::String &name);
+ ScrollText(const Common::String &name, UIElement *owner);
/**
* Sets the element's bounds
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index 947f82f1d52..c2ae23a4147 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -35,6 +35,10 @@ ScrollView::ScrollView(const Common::String &name) :
TextView(name, g_engine) {
}
+ScrollView::ScrollView(const Common::String &name,
+ UIElement *owner) : TextView(name, owner) {
+}
+
void ScrollView::draw() {
frame();
fill();
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index 72f73f3fa94..3c82d41ae41 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -50,6 +50,7 @@ protected:
void writeSymbol(int symbolId);
public:
ScrollView(const Common::String &name);
+ ScrollView(const Common::String &name, UIElement *owner);
virtual ~ScrollView() {}
/**
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 89360bdb835..4f7a162723f 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -64,6 +64,7 @@ MODULE_OBJS := \
mm1/views_enh/character_info.o \
mm1/views_enh/dialogs.o \
mm1/views_enh/game.o \
+ mm1/views_enh/game_messages.o \
mm1/views_enh/map.o \
mm1/views_enh/scroll_text.o \
mm1/views_enh/scroll_view.o \
Commit: be55e6e56f66f5a7c31afca21e9cf147229594df
https://github.com/scummvm/scummvm/commit/be55e6e56f66f5a7c31afca21e9cf147229594df
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:01+01:00
Commit Message:
MM: MM1: Fix grocer text
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 019e37e8705..c3f4d062ae8 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -628,7 +628,7 @@ maps:
blacksmith_inside: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
inn_inside: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
- market_inside: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!WOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
+ market_inside: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!\nWOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
tavern_inside: "STEP UP TO THE BAR (Y/N)?"
temple_inside: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
training_inside: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
Commit: bb518bcf16af090b69c1cb1e0ee7152dd68302b3
https://github.com/scummvm/scummvm/commit/bb518bcf16af090b69c1cb1e0ee7152dd68302b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:01+01:00
Commit Message:
MM: MM1: Word wrap strings in the game messages window
Changed paths:
engines/mm/mm1/views_enh/game_messages.cpp
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/text_view.cpp
diff --git a/engines/mm/mm1/views_enh/game_messages.cpp b/engines/mm/mm1/views_enh/game_messages.cpp
index ba67fefad79..28ce5fce731 100644
--- a/engines/mm/mm1/views_enh/game_messages.cpp
+++ b/engines/mm/mm1/views_enh/game_messages.cpp
@@ -59,6 +59,7 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
clear();
for (auto line : msg._lines) {
Common::String str = capitalize(line._text);
+ str = searchAndReplace(str, "\n", " ");
addText(str, line.y, 0, ALIGN_LEFT, line.x * 8);
}
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index 86ddc920315..158e701858c 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -65,24 +65,52 @@ void ScrollText::addText(const Common::String &str,
Common::Point pt(xp, lineNum * 8);
Graphics::Font &font = _fontReduced ?
g_globals->_fontReduced : g_globals->_fontNormal;
-
- if (align != ALIGN_LEFT) {
- size_t strWidth = font.getStringWidth(str);
-
- if (align == ALIGN_RIGHT) {
- // Right alignment
- if (xp == 0)
- xp = _innerBounds.width();
- pt.x = xp - strWidth;
- } else {
- // Middle alignment
- if (xp == 0)
- xp = _innerBounds.width() / 2;
- pt.x = xp - strWidth / 2;
+ size_t strWidth = font.getStringWidth(str);
+ char *startP = const_cast<char *>(str.c_str());
+ char *endP;
+
+ switch (align) {
+ case ALIGN_LEFT:
+ // We have extra logic for standard left aligned strings to
+ // insert extra newlines as necessary to word-wrap any text
+ // that would go over the edge of the dialog
+ while (*startP && strWidth > _innerBounds.width()) {
+ // Find the last space before a full line
+ endP = startP + strlen(startP) - 1;
+ while (strWidth > _innerBounds.width()) {
+ // Move back to a prior space
+ for (--endP; endP > startP && *endP != ' '; --endP) {
+ }
+ assert(endP > startP);
+
+ strWidth = font.getStringWidth(
+ Common::String(startP, endP));
+ }
+
+ // Add a newline
+ *endP = '\n';
+ startP = endP + 1;
+ strWidth = font.getStringWidth(startP);
}
+ break;
+
+ case ALIGN_MIDDLE:
+ // Middle alignment
+ if (xp == 0)
+ xp = _innerBounds.width() / 2;
+ pt.x = xp - strWidth / 2;
+ break;
+
+ case ALIGN_RIGHT:
+ // Right alignment
+ if (xp == 0)
+ xp = _innerBounds.width();
+ pt.x = xp - strWidth;
+ break;
}
- _lines.push_back(Line(str, pt, color));
+ if (!str.empty())
+ _lines.push_back(Line(str, pt, color));
}
void ScrollText::draw() {
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 98952dcdcaf..266165e4e17 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -50,7 +50,7 @@ void TextView::writeChar(char c) {
if (c == '\r' || c == '\n') {
_textPos.x = 0;
- _textPos.y++;
+ _textPos.y += font.getFontHeight();
} else {
Graphics::ManagedSurface s = getSurface();
if (c != ' ')
Commit: a8c666b3c640a9d9cd4b1547bfa3670b1c86f0b5
https://github.com/scummvm/scummvm/commit/a8c666b3c640a9d9cd4b1547bfa3670b1c86f0b5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:01+01:00
Commit Message:
MM: MM1: Set up so changing _bounds also changes _innerBounds
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/text_view.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 9f2696473d2..e1c3c595bdb 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -145,9 +145,29 @@ void Events::popView() {
/*------------------------------------------------------------------------*/
+Bounds::Bounds(Common::Rect &innerBounds) :
+ Common::Rect(0, 0, 320, 200),
+ _innerBounds(innerBounds) {
+}
+
+Bounds &Bounds::operator=(const Common::Rect &r) {
+ Common::Rect::operator=(r);
+ _innerBounds = r;
+ _innerBounds.grow(-_borderSize);
+ return *this;
+}
+
+void Bounds::setBorderSize(size_t borderSize) {
+ _borderSize = borderSize;
+ _innerBounds = *this;
+ _innerBounds.grow(-_borderSize);
+}
+
+/*------------------------------------------------------------------------*/
+
UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
_name(name), _parent(uiParent),
- _bounds(0, 0, SCREEN_W, SCREEN_H) {
+ _bounds(_innerBounds) {
if (_parent)
_parent->_children.push_back(this);
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index ae2757cbd94..c0717ffb863 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -36,6 +36,17 @@ namespace MM1 {
class Events;
+struct Bounds : public Common::Rect {
+private:
+ Common::Rect &_innerBounds;
+ int _borderSize = 0;
+public:
+ Bounds(Common::Rect &innerBounds);
+ Bounds &operator=(const Common::Rect &r);
+ void setBorderSize(size_t borderSize);
+ size_t borderSize() const { return _borderSize; }
+};
+
class UIElement {
friend class Events;
private:
@@ -43,7 +54,8 @@ private:
protected:
UIElement *_parent;
Common::Array<UIElement *> _children;
- Common::Rect _bounds;
+ Common::Rect _innerBounds;
+ Bounds _bounds;
bool _needsRedraw = true;
Common::String _name;
protected:
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index 158e701858c..52f1d272328 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -38,8 +38,6 @@ ScrollText::ScrollText(const Common::String &name, UIElement *owner) :
void ScrollText::setBounds(const Common::Rect &r) {
ScrollView::setBounds(r);
- _innerBounds = r;
- _innerBounds.grow(-FRAME_BORDER_SIZE);
_rowCount = _innerBounds.height() / FONT_HEIGHT;
}
@@ -65,7 +63,7 @@ void ScrollText::addText(const Common::String &str,
Common::Point pt(xp, lineNum * 8);
Graphics::Font &font = _fontReduced ?
g_globals->_fontReduced : g_globals->_fontNormal;
- size_t strWidth = font.getStringWidth(str);
+ int strWidth = font.getStringWidth(str);
char *startP = const_cast<char *>(str.c_str());
char *endP;
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index e78503d6c82..c59facfa44e 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -54,7 +54,6 @@ public:
private:
size_t _rowCount = 0;
Lines _lines;
- Common::Rect _innerBounds;
public:
ScrollText(const Common::String &name);
ScrollText(const Common::String &name, UIElement *owner);
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index c2ae23a4147..d0984bde7d3 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -32,11 +32,13 @@ namespace ViewsEnh {
#define SYMBOL_HEIGHT FRAME_BORDER_SIZE
ScrollView::ScrollView(const Common::String &name) :
- TextView(name, g_engine) {
+ TextView(name, g_engine) {
+ _bounds.setBorderSize(FRAME_BORDER_SIZE);
}
ScrollView::ScrollView(const Common::String &name,
UIElement *owner) : TextView(name, owner) {
+ _bounds.setBorderSize(FRAME_BORDER_SIZE);
}
void ScrollView::draw() {
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 266165e4e17..679d9b52b3b 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -54,10 +54,13 @@ void TextView::writeChar(char c) {
} else {
Graphics::ManagedSurface s = getSurface();
if (c != ' ')
- font.drawChar(&s, c, _textPos.x, _textPos.y, 0xff);
+ font.drawChar(&s, c,
+ _bounds.borderSize() + _textPos.x,
+ _bounds.borderSize() + _textPos.y,
+ 0xff);
_textPos.x += font.getCharWidth(c);
- if (_textPos.x >= s.w) {
+ if (_textPos.x >= _innerBounds.width()) {
_textPos.x = 0;
_textPos.y += font.getFontHeight();
}
Commit: 3cd64d79fa757b874a242fdca436c63dba9431a5
https://github.com/scummvm/scummvm/commit/3cd64d79fa757b874a242fdca436c63dba9431a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:02+01:00
Commit Message:
MM: MM1: Added messages sub-view for Y/N buttons
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views_enh/game_messages.cpp
engines/mm/mm1/views_enh/game_messages.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/scroll_view.h
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index e1c3c595bdb..dd418dc4c6e 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -146,12 +146,14 @@ void Events::popView() {
/*------------------------------------------------------------------------*/
Bounds::Bounds(Common::Rect &innerBounds) :
- Common::Rect(0, 0, 320, 200),
- _innerBounds(innerBounds) {
+ _bounds(0, 0, 320, 200),
+ _innerBounds(innerBounds),
+ left(_bounds.left), top(_bounds.top),
+ right(_bounds.right), bottom(_bounds.bottom) {
}
Bounds &Bounds::operator=(const Common::Rect &r) {
- Common::Rect::operator=(r);
+ _bounds = r;
_innerBounds = r;
_innerBounds.grow(-_borderSize);
return *this;
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index c0717ffb863..396ad91fe01 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -36,17 +36,35 @@ namespace MM1 {
class Events;
-struct Bounds : public Common::Rect {
+/**
+ * Implements a thunk layer around an element's
+ * bounds, allowing access to it as if it were
+ * a simple Common::Rect, but any changes to it
+ * will also be applied to a linked inner bounds
+ */
+struct Bounds {
private:
+ Common::Rect _bounds;
Common::Rect &_innerBounds;
int _borderSize = 0;
+public:
+ const int16 &left;
+ const int16 ⊤
+ const int16 &right;
+ const int16 ⊥
public:
Bounds(Common::Rect &innerBounds);
+ operator const Common::Rect &() const { return _bounds; }
Bounds &operator=(const Common::Rect &r);
void setBorderSize(size_t borderSize);
size_t borderSize() const { return _borderSize; }
+ int16 width() const { return _bounds.width(); }
+ int16 height() const { return _bounds.height(); }
};
+/**
+ * User interface element
+ */
class UIElement {
friend class Events;
private:
@@ -200,6 +218,9 @@ public:
#undef MESSAGE
};
+/**
+ * Main events and view manager
+ */
class Events : public UIElement, public Mouse {
private:
Graphics::Screen *_screen = nullptr;
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index b5b859ed872..70a44c8b611 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -57,6 +57,7 @@ bool Globals::load(bool isEnhanced) {
if (isEnhanced) {
_mainIcons.load("main.icn");
+ _confirmIcons.load("confirm.icn");
_globalSprites.load("global.icn");
_tileSprites.load("town.til");
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 0717114e79f..b3d6ece1a51 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -49,6 +49,7 @@ public:
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
+ Xeen::SpriteResource _confirmIcons;
Xeen::SpriteResource _globalSprites;
Xeen::SpriteResource _tileSprites;
byte SYMBOLS[20][64];
diff --git a/engines/mm/mm1/views_enh/game_messages.cpp b/engines/mm/mm1/views_enh/game_messages.cpp
index 28ce5fce731..707d7ff0dbd 100644
--- a/engines/mm/mm1/views_enh/game_messages.cpp
+++ b/engines/mm/mm1/views_enh/game_messages.cpp
@@ -22,12 +22,31 @@
#include "common/util.h"
#include "mm/utils/strings.h"
#include "mm/mm1/views_enh/game_messages.h"
+#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
+GameMessages::YesNo::YesNo() :
+ ScrollView("MessagesYesNo", g_events) {
+ _bounds = Common::Rect(234, 18 * 8, 320, 200);
+ addButton(&g_globals->_confirmIcons,
+ Common::Point(14, 10), 0,
+ Common::KeyState(Common::KEYCODE_y, 'y'));
+ addButton(&g_globals->_confirmIcons,
+ Common::Point(40, 10), 2,
+ Common::KeyState(Common::KEYCODE_n, 'n'));
+}
+
+bool GameMessages::YesNo::msgKeypress(const KeypressMessage &msg) {
+ // Pass on any Y/N button presses to the messages area
+ return send("GameMessages", msg);
+}
+
+/*------------------------------------------------------------------------*/
+
GameMessages::GameMessages(UIElement *owner) :
ScrollText("GameMessages", owner) {
}
@@ -36,6 +55,11 @@ void GameMessages::draw() {
// Only draw non-focused messages for a single turn
if (_show || g_events->focusedView() == this) {
ScrollText::draw();
+ if (_ynCallback) {
+ _yesNo.resetSelectedButton();
+ _yesNo.draw();
+ }
+
_show = false;
}
}
@@ -84,6 +108,20 @@ bool GameMessages::msgKeypress(const KeypressMessage &msg) {
return false;
}
+bool GameMessages::msgMouseDown(const MouseDownMessage &msg) {
+ // If yes/no prompting, also pass events to buttons view
+ if (_ynCallback)
+ return send("MessagesYesNo", msg);
+ return false;
+}
+
+bool GameMessages::msgMouseUp(const MouseUpMessage &msg) {
+ // If yes/no prompting, also pass events to buttons view
+ if (_ynCallback)
+ return send("MessagesYesNo", msg);
+ return false;
+}
+
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/game_messages.h b/engines/mm/mm1/views_enh/game_messages.h
index 7b4a07f3e8e..fc3740b9e2e 100644
--- a/engines/mm/mm1/views_enh/game_messages.h
+++ b/engines/mm/mm1/views_enh/game_messages.h
@@ -30,10 +30,16 @@ namespace MM1 {
namespace ViewsEnh {
class GameMessages : public ScrollText {
+ class YesNo : public ScrollView {
+ public:
+ YesNo();
+ bool msgKeypress(const KeypressMessage &msg) override;
+ };
private:
bool _show = false;
YNCallback _ynCallback = nullptr;
KeyCallback _keyCallback = nullptr;
+ YesNo _yesNo;
public:
GameMessages(UIElement *owner);
virtual ~GameMessages() {}
@@ -41,6 +47,8 @@ public:
void draw() override;
bool msgInfo(const InfoMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgMouseDown(const MouseDownMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index d0984bde7d3..fb57da741b3 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -41,10 +41,30 @@ ScrollView::ScrollView(const Common::String &name,
_bounds.setBorderSize(FRAME_BORDER_SIZE);
}
+void ScrollView::addButton(Xeen::SpriteResource *sprites,
+ const Common::Point &pos, int frame,
+ const Common::KeyState &key) {
+ _buttons.push_back(Button(sprites, pos, frame, key));
+}
+
+void ScrollView::resetSelectedButton() {
+ _selectedButton = -1;
+ redraw();
+}
+
void ScrollView::draw() {
frame();
fill();
setTextColor(0);
+
+ Graphics::ManagedSurface s = getSurface();
+ for (uint i = 0; i < _buttons.size(); ++i) {
+ const Button &btn = _buttons[i];
+ btn._sprites->draw(&s,
+ btn._frame + (_selectedButton == (int)i ? 1 : 0),
+ Common::Point(btn._pos.x + _bounds.borderSize(),
+ btn._pos.y + _bounds.borderSize()));
+ }
}
void ScrollView::frame() {
@@ -127,6 +147,48 @@ void ScrollView::writeSymbol(int symbolId) {
_symbolPos.x += SYMBOL_WIDTH;
}
+bool ScrollView::msgFocus(const FocusMessage &msg) {
+ _selectedButton = -1;
+ return TextView::msgFocus(msg);
+}
+
+bool ScrollView::msgMouseDown(const MouseDownMessage &msg) {
+ _selectedButton = getButtonAt(msg._pos);
+ if (_selectedButton != -1) {
+ draw();
+ return true;
+ }
+
+ return false;
+}
+
+bool ScrollView::msgMouseUp(const MouseUpMessage &msg) {
+ // Reset button depressed state
+ if (_selectedButton != -1)
+ draw();
+
+ // If the highlighted button remains the same, trigger it's key
+ int selectedButton = getButtonAt(msg._pos);
+ if (selectedButton != -1 && selectedButton == _selectedButton) {
+ msgKeypress(KeypressMessage(_buttons[selectedButton]._key));
+ return true;
+ }
+
+ return false;
+}
+
+int ScrollView::getButtonAt(const Common::Point &pos) {
+ Common::Rect r(16, 16);
+ for (uint i = 0; i < _buttons.size(); ++i) {
+ r.moveTo(_innerBounds.left + _buttons[i]._pos.x,
+ _innerBounds.top + _buttons[i]._pos.y);
+ if (r.contains(pos))
+ return i;
+ }
+
+ return -1;
+}
+
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index 3c82d41ae41..99045447b2e 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -31,6 +31,21 @@ namespace ViewsEnh {
#define FRAME_BORDER_SIZE 8
class ScrollView : public TextView {
+ struct Button {
+ Xeen::SpriteResource *_sprites;
+ Common::Point _pos;
+ int _frame;
+ Common::KeyState _key;
+
+ Button(Xeen::SpriteResource *sprites,
+ const Common::Point &pos, int frame,
+ const Common::KeyState &key) :
+ _sprites(sprites), _pos(pos), _frame(frame), _key(key) {
+ }
+ };
+private:
+ Common::Array<Button> _buttons;
+ int _selectedButton = -1;
protected:
Common::Point _symbolPos;
protected:
@@ -48,15 +63,54 @@ protected:
* Draw a special symbol
*/
void writeSymbol(int symbolId);
+
+ /**
+ * Get the button at the given position
+ */
+ int getButtonAt(const Common::Point &pos);
public:
ScrollView(const Common::String &name);
ScrollView(const Common::String &name, UIElement *owner);
virtual ~ScrollView() {}
+ /**
+ * Clear the buttons list
+ */
+ void clearButtons() {
+ _buttons.clear();
+ }
+
+ /**
+ * Add a button for display
+ */
+ void addButton(Xeen::SpriteResource *sprites,
+ const Common::Point &pos, int frame,
+ const Common::KeyState &key);
+
+ /**
+ * Reset selected button
+ */
+ void resetSelectedButton();
+
/**
* Draw the view
*/
void draw() override;
+
+ /**
+ * View is focused
+ */
+ bool msgFocus(const FocusMessage &msg) override;
+
+ /**
+ * Mouse down messages
+ */
+ bool msgMouseDown(const MouseDownMessage &msg) override;
+
+ /**
+ * Mouse up messages
+ */
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace ViewsEnh
Commit: 88edd92bf504c8920895c718bae98f76743912f3
https://github.com/scummvm/scummvm/commit/88edd92bf504c8920895c718bae98f76743912f3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:02+01:00
Commit Message:
MM: MM1: Fix word-wrapping occurring exactly at end of line
Changed paths:
engines/mm/mm1/views_enh/game_messages.cpp
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
diff --git a/engines/mm/mm1/views_enh/game_messages.cpp b/engines/mm/mm1/views_enh/game_messages.cpp
index 707d7ff0dbd..91fd6aa0c41 100644
--- a/engines/mm/mm1/views_enh/game_messages.cpp
+++ b/engines/mm/mm1/views_enh/game_messages.cpp
@@ -81,11 +81,8 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
// Process the lines
clear();
- for (auto line : msg._lines) {
- Common::String str = capitalize(line._text);
- str = searchAndReplace(str, "\n", " ");
- addText(str, line.y, 0, ALIGN_LEFT, line.x * 8);
- }
+ for (auto line : msg._lines)
+ addText(line._text, line.y, 0, ALIGN_LEFT, line.x * 8);
redraw();
return true;
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index 52f1d272328..5b9cfc18867 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/views_enh/scroll_text.h"
#include "mm/mm1/globals.h"
+#include "mm/utils/strings.h"
namespace MM {
namespace MM1 {
@@ -41,29 +42,32 @@ void ScrollText::setBounds(const Common::Rect &r) {
_rowCount = _innerBounds.height() / FONT_HEIGHT;
}
-void ScrollText::addLine(const Common::String &str,
+void ScrollText::addLine(const Common::String &msg,
TextAlignment align, byte color) {
if (_lines.size() < _rowCount) {
switch (align) {
case ALIGN_LEFT:
- addText(str, _lines.size(), color, align);
+ addText(msg, _lines.size(), color, align);
break;
case ALIGN_RIGHT:
- addText(str, _lines.size(), color, align);
+ addText(msg, _lines.size(), color, align);
break;
case ALIGN_MIDDLE:
- addText(str, _lines.size(), color, align);
+ addText(msg, _lines.size(), color, align);
break;
}
}
}
-void ScrollText::addText(const Common::String &str,
+void ScrollText::addText(const Common::String &msg,
int lineNum, byte color, TextAlignment align, int xp) {
Common::Point pt(xp, lineNum * 8);
Graphics::Font &font = _fontReduced ?
g_globals->_fontReduced : g_globals->_fontNormal;
- int strWidth = font.getStringWidth(str);
+ int strWidth = font.getStringWidth(msg);
+
+ Common::String str = capitalize(msg);
+ str = searchAndReplace(str, "\n", " ");
char *startP = const_cast<char *>(str.c_str());
char *endP;
@@ -85,9 +89,18 @@ void ScrollText::addText(const Common::String &str,
Common::String(startP, endP));
}
- // Add a newline
- *endP = '\n';
- startP = endP + 1;
+ if (strWidth == _innerBounds.width()) {
+ // Word break exactly at the line end.
+ // So simply get rid of the space
+ uint i = (const char *)endP - str.c_str();
+ str.deleteChar(i);
+ startP = const_cast<char *>(str.c_str() + i);
+ } else {
+ // Add a newline
+ *endP = '\n';
+ startP = endP + 1;
+ }
+
strWidth = font.getStringWidth(startP);
}
break;
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index c59facfa44e..6fb5bf51079 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -78,13 +78,13 @@ public:
/**
* Simplest form that adds lines one at a time
*/
- void addLine(const Common::String &str,
+ void addLine(const Common::String &msg,
TextAlignment align = ALIGN_LEFT, byte color = 0);
/**
* Add a new line fragment for a given position
*/
- void addText(const Common::String &str,
+ void addText(const Common::String &msg,
int lineNum, byte color = 0,
TextAlignment align = ALIGN_LEFT, int xp = 0);
Commit: d1eb30041fbc2efb4f4a4b266169790a0ceac4c4
https://github.com/scummvm/scummvm/commit/d1eb30041fbc2efb4f4a4b266169790a0ceac4c4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:02+01:00
Commit Message:
MM: MM1: Capitalize the word 'I' in messages
This is a stop-gap method. Later on, I'll have
to look into capitalizing other words in messages
in enhanced mode. Like the city names, etc.
Changed paths:
engines/mm/utils/strings.cpp
diff --git a/engines/mm/utils/strings.cpp b/engines/mm/utils/strings.cpp
index 201c8b6e479..ecd0df0a2ea 100644
--- a/engines/mm/utils/strings.cpp
+++ b/engines/mm/utils/strings.cpp
@@ -29,6 +29,10 @@ Common::String capitalize(const Common::String &str) {
bool capitalize = true;
for (uint i = 0; i < str.size(); ++i) {
+ if (!scumm_strnicmp(result.c_str() - 1, " i ", 3))
+ // the word 'I' is always capitalized
+ capitalize = true;
+
if (capitalize) {
result.setChar(toupper(result[i]), i);
capitalize = false;
Commit: 48a505a14de7cf641fcfac3b564e7af05f9983d4
https://github.com/scummvm/scummvm/commit/48a505a14de7cf641fcfac3b564e7af05f9983d4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:02+01:00
Commit Message:
MM: MM1: Beginnings of enhanced locations views
Changed paths:
A engines/mm/mm1/views_enh/locations/location.cpp
A engines/mm/mm1/views_enh/locations/location.h
A engines/mm/mm1/views_enh/locations/market.cpp
A engines/mm/mm1/views_enh/locations/market.h
engines/mm/mm1/views/locations/location.h
engines/mm/mm1/views_enh/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/locations/location.h b/engines/mm/mm1/views/locations/location.h
index fa485d464e1..4575b9be090 100644
--- a/engines/mm/mm1/views/locations/location.h
+++ b/engines/mm/mm1/views/locations/location.h
@@ -30,8 +30,6 @@ namespace Views {
namespace Locations {
class Location : public TextView {
-private:
- int _timeoutCtr = 0;
protected:
Common::String _modeString;
protected:
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index 625d0b2de08..d4a758e9eef 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -33,6 +33,7 @@
//#include "mm/mm1/views/char.h"
#include "mm/mm1/views_enh/character_info.h"
#include "mm/mm1/views_enh/game.h"
+#include "mm/mm1/views_enh/locations/market.h"
namespace MM {
namespace MM1 {
@@ -53,6 +54,7 @@ private:
Views::Title _title;
// Views::ViewCharacters _viewCharacters;
// Views::ViewCharacter _viewCharacter;
+ ViewsEnh::Locations::Market _market;
public:
Dialogs() {}
};
diff --git a/engines/mm/mm1/views_enh/locations/location.cpp b/engines/mm/mm1/views_enh/locations/location.cpp
new file mode 100644
index 00000000000..1540639a7c3
--- /dev/null
+++ b/engines/mm/mm1/views_enh/locations/location.cpp
@@ -0,0 +1,39 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/locations/location.h"
+#include "mm/mm1/globals.h"
+#include "mm/utils/strings.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+namespace Locations {
+
+Location::Location(const Common::String &name) :
+ ScrollView(name) {
+ _bounds = Common::Rect(232, 0, 320, 146);
+}
+
+} // namespace Locations
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/locations/location.h b/engines/mm/mm1/views_enh/locations/location.h
new file mode 100644
index 00000000000..51798545c50
--- /dev/null
+++ b/engines/mm/mm1/views_enh/locations/location.h
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_LOCATIONS_LOCATION_H
+#define MM1_VIEWS_ENH_LOCATIONS_LOCATION_H
+
+#include "mm/mm1/views_enh/scroll_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+namespace Locations {
+
+class Location : public ScrollView {
+public:
+ Location(const Common::String &name);
+};
+
+} // namespace Locations
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
new file mode 100644
index 00000000000..a78115c5792
--- /dev/null
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/locations/market.h"
+#include "mm/mm1/globals.h"
+#include "mm/utils/strings.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+namespace Locations {
+
+Market::Market() : Location("Market") {
+}
+
+void Market::draw() {
+ Location::draw();
+
+}
+
+} // namespace Location
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/locations/market.h b/engines/mm/mm1/views_enh/locations/market.h
new file mode 100644
index 00000000000..f3636e8deb5
--- /dev/null
+++ b/engines/mm/mm1/views_enh/locations/market.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_LOCATIONS_MARKET_H
+#define MM1_VIEWS_ENH_LOCATIONS_MARKET_H
+
+#include "mm/mm1/views_enh/locations/location.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+namespace Locations {
+
+class Market : public Location {
+public:
+ Market();
+
+ /**
+ * Draw the view
+ */
+ void draw() override;
+};
+
+} // namespace Locations
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 4f7a162723f..af36a8292f9 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -69,6 +69,8 @@ MODULE_OBJS := \
mm1/views_enh/scroll_text.o \
mm1/views_enh/scroll_view.o \
mm1/views_enh/text_view.o \
+ mm1/views_enh/locations/location.o \
+ mm1/views_enh/locations/market.o \
mm1/maps/maps.o \
mm1/maps/map.o \
mm1/maps/map00.o \
Commit: b23a11c6ae504fd7ffb4555eadca028066a9a0fd
https://github.com/scummvm/scummvm/commit/b23a11c6ae504fd7ffb4555eadca028066a9a0fd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:02+01:00
Commit Message:
MM: MM1: Close messages area before displaying location
Changed paths:
engines/mm/mm1/views_enh/game_messages.cpp
diff --git a/engines/mm/mm1/views_enh/game_messages.cpp b/engines/mm/mm1/views_enh/game_messages.cpp
index 91fd6aa0c41..1557244208c 100644
--- a/engines/mm/mm1/views_enh/game_messages.cpp
+++ b/engines/mm/mm1/views_enh/game_messages.cpp
@@ -94,8 +94,10 @@ bool GameMessages::msgKeypress(const KeypressMessage &msg) {
_keyCallback(msg);
} else if (msg.keycode == Common::KEYCODE_n) {
close();
+ g_events->drawElements();
} else if (msg.keycode == Common::KEYCODE_y) {
close();
+ g_events->drawElements();
_ynCallback();
}
Commit: 5ec15a97eb724eef187b7e0699aabfaf48ec204d
https://github.com/scummvm/scummvm/commit/5ec15a97eb724eef187b7e0699aabfaf48ec204d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:02+01:00
Commit Message:
MM: MM1: In progress Market location display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/views_enh/game_messages.cpp
engines/mm/mm1/views_enh/locations/location.cpp
engines/mm/mm1/views_enh/locations/location.h
engines/mm/mm1/views_enh/locations/market.cpp
engines/mm/mm1/views_enh/locations/market.h
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c3f4d062ae8..28b87c0b9ae 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -297,6 +297,12 @@ enhdialogs:
exchange: "\x01""37Exch"
conditions:
good: "Good"
+ location:
+ store: "store"
+ options: "options"
+ gold: "gold"
+ market:
+ buy_food: "Buy food"
misc:
exit: "Exit"
stats:
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 83a36293d4d..aaed71179d2 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -50,5 +50,13 @@ void Party::share(TransferKind shareType) {
}
}
+uint Party::getPartyGold() const {
+ uint total = 0;
+ for (uint i = 0; i < size(); ++i)
+ total += (*this)[i]._gold;
+
+ return total;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index fc1e166fcaf..e0690d705d2 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -29,7 +29,15 @@ namespace MM {
namespace MM1 {
struct Party : public Common::Array<Character> {
+ /**
+ * Share food, gold, gems between entire party
+ */
static void share(TransferKind shareType);
+
+ /**
+ * Get the party gold combined
+ */
+ uint getPartyGold() const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/views_enh/game_messages.cpp b/engines/mm/mm1/views_enh/game_messages.cpp
index 1557244208c..ebbfc5e4949 100644
--- a/engines/mm/mm1/views_enh/game_messages.cpp
+++ b/engines/mm/mm1/views_enh/game_messages.cpp
@@ -82,7 +82,8 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
// Process the lines
clear();
for (auto line : msg._lines)
- addText(line._text, line.y, 0, ALIGN_LEFT, line.x * 8);
+ addText(ScrollText::format(line._text),
+ line.y, 0, ALIGN_LEFT, line.x * 8);
redraw();
return true;
diff --git a/engines/mm/mm1/views_enh/locations/location.cpp b/engines/mm/mm1/views_enh/locations/location.cpp
index 1540639a7c3..9affd34dce0 100644
--- a/engines/mm/mm1/views_enh/locations/location.cpp
+++ b/engines/mm/mm1/views_enh/locations/location.cpp
@@ -29,7 +29,7 @@ namespace ViewsEnh {
namespace Locations {
Location::Location(const Common::String &name) :
- ScrollView(name) {
+ ScrollText(name) {
_bounds = Common::Rect(232, 0, 320, 146);
}
diff --git a/engines/mm/mm1/views_enh/locations/location.h b/engines/mm/mm1/views_enh/locations/location.h
index 51798545c50..31f0254f1ef 100644
--- a/engines/mm/mm1/views_enh/locations/location.h
+++ b/engines/mm/mm1/views_enh/locations/location.h
@@ -22,14 +22,14 @@
#ifndef MM1_VIEWS_ENH_LOCATIONS_LOCATION_H
#define MM1_VIEWS_ENH_LOCATIONS_LOCATION_H
-#include "mm/mm1/views_enh/scroll_view.h"
+#include "mm/mm1/views_enh/scroll_text.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
namespace Locations {
-class Location : public ScrollView {
+class Location : public ScrollText {
public:
Location(const Common::String &name);
};
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
index a78115c5792..820ad882cf6 100644
--- a/engines/mm/mm1/views_enh/locations/market.cpp
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -31,6 +31,24 @@ namespace Locations {
Market::Market() : Location("Market") {
}
+bool Market::msgFocus(const FocusMessage &msg) {
+ Maps::Map &map = *g_maps->_currentMap;
+ _foodCost = FOOD_COST[map[0] - 1];
+
+ clear();
+ addText(STRING["enhdialogs.location.store"], 0, ALIGN_MIDDLE);
+ addText(STRING["enhdialogs.location.options"], 1, ALIGN_MIDDLE);
+ addText(STRING["enhdialogs.market.buy_food"], 6, ALIGN_MIDDLE);
+ addText(Common::String::format("%d %s",
+ _foodCost, STRING["dialogs.market.gp"].c_str()),
+ 7, ALIGN_MIDDLE);
+ addText(STRING["enhdialogs.location.gold"], 10, ALIGN_LEFT);
+
+ uint gold = g_globals->_party.getPartyGold();
+ addText(Common::String::format("%d", gold), 10, ALIGN_RIGHT);
+ return true;
+}
+
void Market::draw() {
Location::draw();
diff --git a/engines/mm/mm1/views_enh/locations/market.h b/engines/mm/mm1/views_enh/locations/market.h
index f3636e8deb5..6bae1588de2 100644
--- a/engines/mm/mm1/views_enh/locations/market.h
+++ b/engines/mm/mm1/views_enh/locations/market.h
@@ -23,16 +23,21 @@
#define MM1_VIEWS_ENH_LOCATIONS_MARKET_H
#include "mm/mm1/views_enh/locations/location.h"
+#include "mm/mm1/data/locations.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
namespace Locations {
-class Market : public Location {
+class Market : public Location, public MarketData {
+private:
+ int _foodCost = 0;
public:
Market();
+ bool msgFocus(const FocusMessage &msg) override;
+
/**
* Draw the view
*/
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index 5b9cfc18867..8257f7ff0ec 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -42,32 +42,36 @@ void ScrollText::setBounds(const Common::Rect &r) {
_rowCount = _innerBounds.height() / FONT_HEIGHT;
}
-void ScrollText::addLine(const Common::String &msg,
+void ScrollText::addLine(const Common::String &str,
TextAlignment align, byte color) {
if (_lines.size() < _rowCount) {
switch (align) {
case ALIGN_LEFT:
- addText(msg, _lines.size(), color, align);
+ addText(str, _lines.size(), color, align);
break;
case ALIGN_RIGHT:
- addText(msg, _lines.size(), color, align);
+ addText(str, _lines.size(), color, align);
break;
case ALIGN_MIDDLE:
- addText(msg, _lines.size(), color, align);
+ addText(str, _lines.size(), color, align);
break;
}
}
}
-void ScrollText::addText(const Common::String &msg,
+Common::String ScrollText::format(const Common::String &str) {
+ Common::String s = capitalize(str);
+ return searchAndReplace(s, "\n", " ");
+}
+
+void ScrollText::addText(const Common::String &s,
int lineNum, byte color, TextAlignment align, int xp) {
+ Common::String str = s;
Common::Point pt(xp, lineNum * 8);
Graphics::Font &font = _fontReduced ?
g_globals->_fontReduced : g_globals->_fontNormal;
- int strWidth = font.getStringWidth(msg);
- Common::String str = capitalize(msg);
- str = searchAndReplace(str, "\n", " ");
+ int strWidth = font.getStringWidth(str);
char *startP = const_cast<char *>(str.c_str());
char *endP;
@@ -131,8 +135,7 @@ void ScrollText::draw() {
for (Lines::const_iterator i = begin();
i != end(); ++i) {
setTextColor(i->_color);
- writeString(i->_pos.x + FRAME_BORDER_SIZE,
- i->_pos.y + FRAME_BORDER_SIZE, i->_str);
+ writeString(i->_pos.x, i->_pos.y, i->_str);
}
}
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index 6fb5bf51079..0ba11e3cf26 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -68,6 +68,12 @@ public:
Lines::const_iterator begin() const { return _lines.begin(); }
Lines::const_iterator end() const { return _lines.end(); }
+ /**
+ * Helper function for formatting original game
+ * capitals only text into normal upper/lowercase text
+ */
+ static Common::String format(const Common::String &str);
+
/**
* Clear the lines
*/
@@ -78,15 +84,20 @@ public:
/**
* Simplest form that adds lines one at a time
*/
- void addLine(const Common::String &msg,
+ void addLine(const Common::String &str,
TextAlignment align = ALIGN_LEFT, byte color = 0);
/**
* Add a new line fragment for a given position
*/
- void addText(const Common::String &msg,
+ void addText(const Common::String &str,
int lineNum, byte color = 0,
TextAlignment align = ALIGN_LEFT, int xp = 0);
+ void addText(const Common::String &str,
+ int lineNum, TextAlignment align = ALIGN_LEFT,
+ int xp = 0) {
+ addText(str, lineNum, 0, align, xp);
+ }
/**
* Draw the view
@@ -96,12 +107,12 @@ public:
/**
* Handle keypress events
*/
- bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &str) override;
/**
* Handle mouse clicks
*/
- bool msgMouseUp(const MouseUpMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &str) override;
};
} // namespace ViewsEnh
Commit: d36366d1224b064f446f8169cbe9c06bb083b526
https://github.com/scummvm/scummvm/commit/d36366d1224b064f446f8169cbe9c06bb083b526
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:02+01:00
Commit Message:
MM: MM1: Market location buttons
Changed paths:
engines/mm/mm1/views_enh/locations/market.cpp
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
index 820ad882cf6..e54a30087ae 100644
--- a/engines/mm/mm1/views_enh/locations/market.cpp
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -29,6 +29,14 @@ namespace ViewsEnh {
namespace Locations {
Market::Market() : Location("Market") {
+ addButton(&g_globals->_confirmIcons,
+ Common::Point(_innerBounds.width() / 2 - 24,
+ _innerBounds.height() - 32),
+ 0, Common::KEYCODE_y);
+ addButton(&g_globals->_confirmIcons,
+ Common::Point(_innerBounds.width() / 2 + 4,
+ _innerBounds.height() - 32),
+ 2, Common::KEYCODE_n);
}
bool Market::msgFocus(const FocusMessage &msg) {
Commit: 5016ae39756a7ce11ccac7b86cb3f3da7fa58e30
https://github.com/scummvm/scummvm/commit/5016ae39756a7ce11ccac7b86cb3f3da7fa58e30
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:03+01:00
Commit Message:
MM: MM1: Fix redraw after releasing view buttons
Changed paths:
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
engines/mm/mm1/views_enh/scroll_view.cpp
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index 8257f7ff0ec..7bda7a15dd1 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -139,20 +139,6 @@ void ScrollText::draw() {
}
}
-bool ScrollText::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_ESCAPE) {
- close();
- return true;
- }
-
- return false;
-}
-
-bool ScrollText::msgMouseUp(const MouseUpMessage &msg) {
- close();
- return true;
-}
-
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index 0ba11e3cf26..8fe70453aff 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -103,16 +103,6 @@ public:
* Draw the view
*/
void draw() override;
-
- /**
- * Handle keypress events
- */
- bool msgKeypress(const KeypressMessage &str) override;
-
- /**
- * Handle mouse clicks
- */
- bool msgMouseUp(const MouseUpMessage &str) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index fb57da741b3..c78dc8a9226 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -163,8 +163,9 @@ bool ScrollView::msgMouseDown(const MouseDownMessage &msg) {
}
bool ScrollView::msgMouseUp(const MouseUpMessage &msg) {
- // Reset button depressed state
- if (_selectedButton != -1)
+ int oldSelection = _selectedButton;
+ _selectedButton = -1;
+ if (oldSelection != -1)
draw();
// If the highlighted button remains the same, trigger it's key
Commit: d5db43209fa45dbc4025a8538e1327b921d308e2
https://github.com/scummvm/scummvm/commit/d5db43209fa45dbc4025a8538e1327b921d308e2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:03+01:00
Commit Message:
MM: MM1: Cleanup of deprecated delay code
Changed paths:
engines/mm/mm1/data/locations.h
engines/mm/mm1/events.h
engines/mm/mm1/views/locations/market.cpp
engines/mm/mm1/views/locations/market.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/engines/mm/mm1/data/locations.h b/engines/mm/mm1/data/locations.h
index 291d4d998dc..9e2890775c3 100644
--- a/engines/mm/mm1/data/locations.h
+++ b/engines/mm/mm1/data/locations.h
@@ -67,6 +67,8 @@ struct BuyMiscData {
};
};
+#define MAX_FOOD 40
+
struct MarketData {
const byte FOOD_COST[4] = { 5, 10, 20, 200 };
};
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 396ad91fe01..fbb97582d76 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -91,6 +91,13 @@ protected:
*/
void delayFrames(uint frames);
+ /**
+ * Returns true if a delay is active
+ */
+ bool isDelayActive() const {
+ return _timeoutCtr != 0;
+ }
+
/**
* Called when an active timeout countdown expired
*/
diff --git a/engines/mm/mm1/views/locations/market.cpp b/engines/mm/mm1/views/locations/market.cpp
index 1dafe54e491..f552e47d79f 100644
--- a/engines/mm/mm1/views/locations/market.cpp
+++ b/engines/mm/mm1/views/locations/market.cpp
@@ -30,9 +30,6 @@ namespace MM1 {
namespace Views {
namespace Locations {
-#define TOTAL_FOOD 40
-#define DISPLAY_TIMEOUT (3 * FRAME_RATE)
-
Market::Market() : Location("Market") {
_bounds = getLineBounds(21, 24);
}
@@ -53,8 +50,7 @@ bool Market::msgKeypress(const KeypressMessage &msg) {
leave();
break;
case Common::KEYCODE_y:
- if (!_displayCtr)
- buyFood();
+ buyFood();
break;
default:
break;
@@ -72,12 +68,6 @@ void Market::draw() {
writeString(10, 2, STRING["dialogs.market.will_you_pay"]);
}
-bool Market::tick() {
- if (_displayCtr && --_displayCtr == 0)
- leave();
- return false;
-}
-
void Market::buyFood() {
int foodPurchased = 0;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
@@ -91,7 +81,7 @@ void Market::buyFood() {
STRING["dialogs.market.no_gold"]
);
- _displayCtr = DISPLAY_TIMEOUT;
+ delaySeconds(3);
}
bool Market::buyFood(Character *c) {
@@ -100,11 +90,15 @@ bool Market::buyFood(Character *c) {
return false;
c->_gold = tempGold;
- c->_food = TOTAL_FOOD;
+ c->_food = MAX_FOOD;
return true;
}
+void Market::timeout() {
+ leave();
+}
+
} // namespace Locations
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/locations/market.h b/engines/mm/mm1/views/locations/market.h
index e5b72231d4a..63eae4f1ec7 100644
--- a/engines/mm/mm1/views/locations/market.h
+++ b/engines/mm/mm1/views/locations/market.h
@@ -34,7 +34,6 @@ namespace Locations {
class Market : public Location, public MarketData {
private:
int _foodCost = 0;
- int _displayCtr = 0;
private:
/**
* Buys food
@@ -52,7 +51,11 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
void draw() override;
- bool tick() override;
+
+ /**
+ * Leaves market after displaying result message
+ */
+ void timeout() override;
};
} // namespace Locations
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 079fa709e34..1c62330fcb6 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -127,18 +127,6 @@ void TextView::escToGoBack(int x) {
writeString(x, 24, STRING["dialogs.misc.go_back"]);
}
-void TextView::delaySeconds(uint seconds) {
- _timeoutCtr = seconds * FRAME_RATE;
-}
-
-bool TextView::tick() {
- if (_timeoutCtr && --_timeoutCtr == 0) {
- timeout();
- }
-
- return UIElement::tick();
-}
-
void TextView::timeout() {
redraw();
}
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 5d3342bf01f..a47db3f3c7c 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -33,8 +33,6 @@ namespace Views {
#define TEXT_H 25
class TextView : public UIElement {
-private:
- int _timeoutCtr = 0;
protected:
Common::Point _textPos;
byte _bgColor = 0xff;
@@ -89,11 +87,6 @@ protected:
*/
void escToGoBack(int x = 12);
- /**
- * Set a delay countdown
- */
- void delaySeconds(uint seconds);
-
/**
* Called when an active timeout countdown expired
*/
@@ -103,13 +96,6 @@ public:
TextView(const Common::String &name);
TextView(const Common::String &name, UIElement *owner);
virtual ~TextView() {}
-
- /**
- * Frame tick
- */
- bool tick() override;
-
-
};
} // namespace Views
Commit: f14ec8f45a5009de8fdcd6bffa1eb731e27ad85e
https://github.com/scummvm/scummvm/commit/f14ec8f45a5009de8fdcd6bffa1eb731e27ad85e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:03+01:00
Commit Message:
MM: MM1: Further implementation of Market location
Changed paths:
engines/mm/mm1/views_enh/locations/location.cpp
engines/mm/mm1/views_enh/locations/location.h
engines/mm/mm1/views_enh/locations/market.cpp
engines/mm/mm1/views_enh/locations/market.h
diff --git a/engines/mm/mm1/views_enh/locations/location.cpp b/engines/mm/mm1/views_enh/locations/location.cpp
index 9affd34dce0..e63ef2875d5 100644
--- a/engines/mm/mm1/views_enh/locations/location.cpp
+++ b/engines/mm/mm1/views_enh/locations/location.cpp
@@ -33,6 +33,12 @@ Location::Location(const Common::String &name) :
_bounds = Common::Rect(232, 0, 320, 146);
}
+void Location::leave() {
+ g_maps->turnAround();
+ close();
+ g_events->redraw();
+}
+
} // namespace Locations
} // namespace ViewsEnh
} // namespace MM1
diff --git a/engines/mm/mm1/views_enh/locations/location.h b/engines/mm/mm1/views_enh/locations/location.h
index 31f0254f1ef..dda2e418f65 100644
--- a/engines/mm/mm1/views_enh/locations/location.h
+++ b/engines/mm/mm1/views_enh/locations/location.h
@@ -32,6 +32,11 @@ namespace Locations {
class Location : public ScrollText {
public:
Location(const Common::String &name);
+
+ /**
+ * Leave the location, turning around
+ */
+ void leave();
};
} // namespace Locations
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
index e54a30087ae..b7e42c54a18 100644
--- a/engines/mm/mm1/views_enh/locations/market.cpp
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -57,9 +57,69 @@ bool Market::msgFocus(const FocusMessage &msg) {
return true;
}
-void Market::draw() {
- Location::draw();
+bool Market::msgKeypress(const KeypressMessage &msg) {
+ if (isDelayActive()) {
+ // Any keypress after purchase made closes
+ leave();
+ return true;
+ } else {
+ switch (msg.keycode) {
+ case Common::KEYCODE_y:
+ buyFood();
+ return true;
+ case Common::KEYCODE_n:
+ case Common::KEYCODE_ESCAPE:
+ leave();
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+void Market::buyFood() {
+ int numPurchases = 0;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (buyFood(&g_globals->_party[i]))
+ ++numPurchases;
+ }
+
+ clearSurface();
+ writeString(10, 2, numPurchases ?
+ STRING["dialogs.market.thankyou"] :
+ STRING["dialogs.market.no_gold"]
+ );
+
+ delaySeconds(3);
+}
+
+bool Market::buyFood(Character *c) {
+ if (c->_food == MAX_FOOD)
+ return true;
+
+ int tempGold = (int)c->_gold - _foodCost;
+ if (tempGold >= 0) {
+ // Reduce character's gold
+ c->_gold = tempGold;
+ } else {
+ // Fall back on any one in the party with gold
+ uint i;
+ for (i = 0; i < g_globals->_party.size(); ++i) {
+ if (g_globals->_party[i]._gold >= _foodCost) {
+ g_globals->_party[i]._gold -= _foodCost;
+ break;
+ }
+ }
+ if (i == g_globals->_party.size())
+ return false;
+ }
+
+ // Food purchased
+ c->_food = MAX_FOOD;
+ return true;
}
} // namespace Location
diff --git a/engines/mm/mm1/views_enh/locations/market.h b/engines/mm/mm1/views_enh/locations/market.h
index 6bae1588de2..4c5de9c37e3 100644
--- a/engines/mm/mm1/views_enh/locations/market.h
+++ b/engines/mm/mm1/views_enh/locations/market.h
@@ -23,6 +23,7 @@
#define MM1_VIEWS_ENH_LOCATIONS_MARKET_H
#include "mm/mm1/views_enh/locations/location.h"
+#include "mm/mm1/data/char.h"
#include "mm/mm1/data/locations.h"
namespace MM {
@@ -32,16 +33,23 @@ namespace Locations {
class Market : public Location, public MarketData {
private:
- int _foodCost = 0;
+ uint _foodCost = 0;
+private:
+ /**
+ * Buys food for party
+ */
+ void buyFood();
+
+ /**
+ * Has a single character buy food
+ */
+ bool buyFood(Character *c);
+
public:
Market();
bool msgFocus(const FocusMessage &msg) override;
-
- /**
- * Draw the view
- */
- void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace Locations
Commit: 37605e9150d5dd0d90cb215ae076841b86179c91
https://github.com/scummvm/scummvm/commit/37605e9150d5dd0d90cb215ae076841b86179c91
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:03+01:00
Commit Message:
MM: MM1: Correct text/icon offsets in Character Info view
Changed paths:
engines/mm/mm1/views_enh/character_info.cpp
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index da032871c87..ea818a0829f 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -162,7 +162,8 @@ bool CharacterInfo::msgMouseUp(const MouseUpMessage &msg) {
// Check if a stat icon was clicked
Common::Rect r(16, 16);
for (int i = 0; i < ICONS_COUNT; ++i) {
- r.moveTo(ICONS[i]._x + 8, ICONS[i]._y + 8);
+ r.moveTo(_innerBounds.left + ICONS[i]._x,
+ _innerBounds.top + ICONS[i]._y);
if (r.contains(msg._pos)) {
showAttribute(i);
return true;
@@ -189,28 +190,28 @@ void CharacterInfo::drawTitle() {
capitalize(STRING[Common::String::format("stats.classes.%d", (int)c._class)]).c_str()
);
- writeString(8, 8, msg);
+ writeString(0, 0, msg);
}
void CharacterInfo::drawIcons() {
Graphics::ManagedSurface s = getSurface();
for (int i = 0; i < CHAR_ICONS_COUNT; ++i) {
_viewIcon.draw(&s, ICONS[i]._frame,
- Common::Point(ICONS[i]._x + FRAME_BORDER_SIZE,
- ICONS[i]._y + FRAME_BORDER_SIZE));
+ Common::Point(ICONS[i]._x + _bounds.borderSize(),
+ ICONS[i]._y + _bounds.borderSize()));
}
// Text for buttons
- writeString(285, 33, STRING["enhdialogs.character.item"]);
- writeString(282, 65, STRING["enhdialogs.character.quick"]);
- writeString(284, 98, STRING["enhdialogs.character.exchange"]);
- writeString(286, 130, STRING["enhdialogs.misc.exit"]);
+ writeString(277, 25, STRING["enhdialogs.character.item"]);
+ writeString(275, 57, STRING["enhdialogs.character.quick"]);
+ writeString(276, 90, STRING["enhdialogs.character.exchange"]);
+ writeString(278, 122, STRING["enhdialogs.misc.exit"]);
}
void CharacterInfo::drawStats() {
// Draw stat titles
for (int i = 0; i < 18; ++i) {
- writeString(ICONS[i]._x + 35, ICONS[i]._y + 10,
+ writeString(ICONS[i]._x + 27, ICONS[i]._y + 2,
ICONS_TEXT[i]);
}
@@ -237,7 +238,7 @@ void CharacterInfo::drawStats() {
if (i == 12)
continue;
- Common::Point pt(ICONS[i]._x + 35, ICONS[i]._y + 20);
+ Common::Point pt(ICONS[i]._x + 27, ICONS[i]._y + 12);
if (i < 10)
pt.x += 8 + (CURR[i] < 10 ? 8 : 0);
@@ -267,7 +268,7 @@ void CharacterInfo::drawStats() {
setTextColor(32);
}
- writeString(204, 128, condStr);
+ writeString(196, 120, condStr);
}
int CharacterInfo::statColor(int amount, int threshold) {
Commit: 45d6b97ac18d154d75a216bc3c994666c8946b7b
https://github.com/scummvm/scummvm/commit/45d6b97ac18d154d75a216bc3c994666c8946b7b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:03+01:00
Commit Message:
MM: MM1: Fix stat popups in character info view
Changed paths:
A engines/mm/mm1/views_enh/scroll_popup.cpp
A engines/mm/mm1/views_enh/scroll_popup.h
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_info.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index ea818a0829f..ede2cedf11c 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -160,7 +160,7 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
bool CharacterInfo::msgMouseUp(const MouseUpMessage &msg) {
// Check if a stat icon was clicked
- Common::Rect r(16, 16);
+ Common::Rect r(25, 22);
for (int i = 0; i < ICONS_COUNT; ++i) {
r.moveTo(_innerBounds.left + ICONS[i]._x,
_innerBounds.top + ICONS[i]._y);
diff --git a/engines/mm/mm1/views_enh/character_info.h b/engines/mm/mm1/views_enh/character_info.h
index 2980d23d0fd..bc9aca7693d 100644
--- a/engines/mm/mm1/views_enh/character_info.h
+++ b/engines/mm/mm1/views_enh/character_info.h
@@ -23,7 +23,7 @@
#define MM1_VIEWS_ENH_CHARACTER_INFO_H
#include "mm/mm1/views_enh/scroll_view.h"
-#include "mm/mm1/views_enh/scroll_text.h"
+#include "mm/mm1/views_enh/scroll_popup.h"
#include "mm/xeen/sprites.h"
namespace MM {
@@ -42,7 +42,7 @@ private:
const char *ICONS_TEXT[CHAR_ICONS_COUNT];
int _cursorCell = 0;
bool _cursorVisible = false;
- ScrollText _statInfo;
+ ScrollPopup _statInfo;
private:
/**
* Draw the title text
diff --git a/engines/mm/mm1/views_enh/scroll_popup.cpp b/engines/mm/mm1/views_enh/scroll_popup.cpp
new file mode 100644
index 00000000000..b33112a4c1e
--- /dev/null
+++ b/engines/mm/mm1/views_enh/scroll_popup.cpp
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/scroll_popup.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+ScrollPopup::ScrollPopup(const Common::String &name) :
+ ScrollText("ScrollPopup") {
+}
+
+bool ScrollPopup::msgKeypress(const KeypressMessage &msg) {
+ close();
+ return true;
+}
+
+bool ScrollPopup::msgMouseUp(const MouseUpMessage &msg) {
+ close();
+ return true;
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/scroll_popup.h b/engines/mm/mm1/views_enh/scroll_popup.h
new file mode 100644
index 00000000000..dea74ce6a80
--- /dev/null
+++ b/engines/mm/mm1/views_enh/scroll_popup.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_SCROLL_POPUP_H
+#define MM1_VIEWS_ENH_SCROLL_POPUP_H
+
+#include "mm/mm1/views_enh/scroll_text.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class ScrollPopup : public ScrollText {
+public:
+ ScrollPopup(const Common::String &name);
+
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index af36a8292f9..2215fa4d615 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -66,6 +66,7 @@ MODULE_OBJS := \
mm1/views_enh/game.o \
mm1/views_enh/game_messages.o \
mm1/views_enh/map.o \
+ mm1/views_enh/scroll_popup.o \
mm1/views_enh/scroll_text.o \
mm1/views_enh/scroll_view.o \
mm1/views_enh/text_view.o \
Commit: 27ff7e466333f6a47931258102f775987ab688e5
https://github.com/scummvm/scummvm/commit/27ff7e466333f6a47931258102f775987ab688e5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:03+01:00
Commit Message:
MM: MM1: Switch to ScrollView as a base class for Location
Changed paths:
engines/mm/mm1/views_enh/locations/location.cpp
engines/mm/mm1/views_enh/locations/location.h
engines/mm/mm1/views_enh/locations/market.cpp
engines/mm/mm1/views_enh/locations/market.h
engines/mm/mm1/views_enh/scroll_text.cpp
engines/mm/mm1/views_enh/scroll_text.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/text_view.cpp
engines/mm/mm1/views_enh/text_view.h
diff --git a/engines/mm/mm1/views_enh/locations/location.cpp b/engines/mm/mm1/views_enh/locations/location.cpp
index e63ef2875d5..856eb03d2a0 100644
--- a/engines/mm/mm1/views_enh/locations/location.cpp
+++ b/engines/mm/mm1/views_enh/locations/location.cpp
@@ -29,7 +29,7 @@ namespace ViewsEnh {
namespace Locations {
Location::Location(const Common::String &name) :
- ScrollText(name) {
+ ScrollView(name) {
_bounds = Common::Rect(232, 0, 320, 146);
}
diff --git a/engines/mm/mm1/views_enh/locations/location.h b/engines/mm/mm1/views_enh/locations/location.h
index dda2e418f65..9a5941aa49e 100644
--- a/engines/mm/mm1/views_enh/locations/location.h
+++ b/engines/mm/mm1/views_enh/locations/location.h
@@ -22,14 +22,14 @@
#ifndef MM1_VIEWS_ENH_LOCATIONS_LOCATION_H
#define MM1_VIEWS_ENH_LOCATIONS_LOCATION_H
-#include "mm/mm1/views_enh/scroll_text.h"
+#include "mm/mm1/views_enh/scroll_view.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
namespace Locations {
-class Location : public ScrollText {
+class Location : public ScrollView {
public:
Location(const Common::String &name);
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
index b7e42c54a18..831e09735e2 100644
--- a/engines/mm/mm1/views_enh/locations/market.cpp
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -42,19 +42,22 @@ Market::Market() : Location("Market") {
bool Market::msgFocus(const FocusMessage &msg) {
Maps::Map &map = *g_maps->_currentMap;
_foodCost = FOOD_COST[map[0] - 1];
+ return true;
+}
- clear();
- addText(STRING["enhdialogs.location.store"], 0, ALIGN_MIDDLE);
- addText(STRING["enhdialogs.location.options"], 1, ALIGN_MIDDLE);
- addText(STRING["enhdialogs.market.buy_food"], 6, ALIGN_MIDDLE);
- addText(Common::String::format("%d %s",
+void Market::draw() {
+ Location::draw();
+
+ writeLine(0, STRING["enhdialogs.location.store"],ALIGN_MIDDLE);
+ writeLine(1, STRING["enhdialogs.location.options"], ALIGN_MIDDLE);
+ writeLine(6, STRING["enhdialogs.market.buy_food"], ALIGN_MIDDLE);
+ writeLine(7, Common::String::format("%d %s",
_foodCost, STRING["dialogs.market.gp"].c_str()),
- 7, ALIGN_MIDDLE);
- addText(STRING["enhdialogs.location.gold"], 10, ALIGN_LEFT);
+ ALIGN_MIDDLE);
+ writeLine(10, STRING["enhdialogs.location.gold"], ALIGN_LEFT);
uint gold = g_globals->_party.getPartyGold();
- addText(Common::String::format("%d", gold), 10, ALIGN_RIGHT);
- return true;
+ writeLine(10, Common::String::format("%d", gold), ALIGN_RIGHT);
}
bool Market::msgKeypress(const KeypressMessage &msg) {
diff --git a/engines/mm/mm1/views_enh/locations/market.h b/engines/mm/mm1/views_enh/locations/market.h
index 4c5de9c37e3..a123dedad37 100644
--- a/engines/mm/mm1/views_enh/locations/market.h
+++ b/engines/mm/mm1/views_enh/locations/market.h
@@ -49,6 +49,7 @@ public:
Market();
bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
diff --git a/engines/mm/mm1/views_enh/scroll_text.cpp b/engines/mm/mm1/views_enh/scroll_text.cpp
index 7bda7a15dd1..39f056d109a 100644
--- a/engines/mm/mm1/views_enh/scroll_text.cpp
+++ b/engines/mm/mm1/views_enh/scroll_text.cpp
@@ -43,7 +43,7 @@ void ScrollText::setBounds(const Common::Rect &r) {
}
void ScrollText::addLine(const Common::String &str,
- TextAlignment align, byte color) {
+ TextAlign align, byte color) {
if (_lines.size() < _rowCount) {
switch (align) {
case ALIGN_LEFT:
@@ -65,7 +65,7 @@ Common::String ScrollText::format(const Common::String &str) {
}
void ScrollText::addText(const Common::String &s,
- int lineNum, byte color, TextAlignment align, int xp) {
+ int lineNum, byte color, TextAlign align, int xp) {
Common::String str = s;
Common::Point pt(xp, lineNum * 8);
Graphics::Font &font = _fontReduced ?
diff --git a/engines/mm/mm1/views_enh/scroll_text.h b/engines/mm/mm1/views_enh/scroll_text.h
index 8fe70453aff..3239200189d 100644
--- a/engines/mm/mm1/views_enh/scroll_text.h
+++ b/engines/mm/mm1/views_enh/scroll_text.h
@@ -31,10 +31,6 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
-enum TextAlignment {
- ALIGN_LEFT, ALIGN_RIGHT, ALIGN_MIDDLE
-};
-
/**
* Derived scroll class for displaying static text
*/
@@ -85,16 +81,16 @@ public:
* Simplest form that adds lines one at a time
*/
void addLine(const Common::String &str,
- TextAlignment align = ALIGN_LEFT, byte color = 0);
+ TextAlign align = ALIGN_LEFT, byte color = 0);
/**
* Add a new line fragment for a given position
*/
void addText(const Common::String &str,
int lineNum, byte color = 0,
- TextAlignment align = ALIGN_LEFT, int xp = 0);
+ TextAlign align = ALIGN_LEFT, int xp = 0);
void addText(const Common::String &str,
- int lineNum, TextAlignment align = ALIGN_LEFT,
+ int lineNum, TextAlign align = ALIGN_LEFT,
int xp = 0) {
addText(str, lineNum, 0, align, xp);
}
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index c78dc8a9226..c46fdc4efcf 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -170,7 +170,7 @@ bool ScrollView::msgMouseUp(const MouseUpMessage &msg) {
// If the highlighted button remains the same, trigger it's key
int selectedButton = getButtonAt(msg._pos);
- if (selectedButton != -1 && selectedButton == _selectedButton) {
+ if (selectedButton != -1 && selectedButton == oldSelection) {
msgKeypress(KeypressMessage(_buttons[selectedButton]._key));
return true;
}
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 679d9b52b3b..5a3f9fb68c5 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -42,11 +42,15 @@ byte TextView::setTextColor(byte col) {
return oldColor;
}
+Graphics::Font *TextView::getFont() const {
+ return _fontReduced ? &g_globals->_fontReduced :
+ &g_globals->_fontNormal;
+}
+
void TextView::writeChar(char c) {
assert((unsigned char)c < 0x80);
XeenFont::setColors(_colorsNum);
- Graphics::Font &font = _fontReduced ?
- g_globals->_fontReduced : g_globals->_fontNormal;
+ Graphics::Font &font = *getFont();
if (c == '\r' || c == '\n') {
_textPos.x = 0;
@@ -91,9 +95,20 @@ void TextView::writeString(const Common::String &str) {
}
}
-void TextView::writeString(int x, int y, const Common::String &str) {
+void TextView::writeString(int x, int y, const Common::String &str,
+ TextAlign align) {
_textPos.x = x;
_textPos.y = y;
+
+ if (align != ALIGN_LEFT && x == 0) {
+ int strWidth = getFont()->getStringWidth(str);
+
+ if (align == ALIGN_MIDDLE)
+ _textPos.x = MAX((_innerBounds.width() - strWidth) / 2, 0);
+ else
+ _textPos.x = MAX(_innerBounds.width() - strWidth, 0);
+ }
+
writeString(str);
}
@@ -107,6 +122,11 @@ void TextView::writeNumber(int x, int y, int val) {
writeNumber(val);
}
+void TextView::writeLine(int lineNum, const Common::String &str,
+ TextAlign align, int xp) {
+ writeString(xp, lineNum * 8, str, align);
+}
+
void TextView::newLine() {
_textPos.x = 0;
_textPos.y++;
diff --git a/engines/mm/mm1/views_enh/text_view.h b/engines/mm/mm1/views_enh/text_view.h
index b3c4fcb8e12..1ce1c52f776 100644
--- a/engines/mm/mm1/views_enh/text_view.h
+++ b/engines/mm/mm1/views_enh/text_view.h
@@ -22,13 +22,20 @@
#ifndef MM1_VIEWS_ENH_TEXT_VIEW_H
#define MM1_VIEWS_ENH_TEXT_VIEW_H
+#include "graphics/font.h"
#include "mm/mm1/events.h"
namespace MM {
namespace MM1 {
namespace ViewsEnh {
+enum TextAlign {
+ ALIGN_LEFT, ALIGN_RIGHT, ALIGN_MIDDLE
+};
+
class TextView : public UIElement {
+private:
+ Graphics::Font *getFont() const;
protected:
Common::Point _textPos;
int _colorsNum = 0;
@@ -49,7 +56,8 @@ protected:
* Write some text
*/
void writeString(const Common::String &str);
- void writeString(int x, int y, const Common::String &str);
+ void writeString(int x, int y, const Common::String &str,
+ TextAlign align = ALIGN_LEFT);
/**
* Write a number
@@ -57,6 +65,12 @@ protected:
void writeNumber(int val);
void writeNumber(int x, int y, int val);
+ /**
+ * Write a line
+ */
+ void writeLine(int lineNum, const Common::String &str,
+ TextAlign align = ALIGN_LEFT, int xp = 0);
+
/**
* Move the text position to the next line
*/
Commit: c425b690eba96777aca4af880f69e0f1d995daf4
https://github.com/scummvm/scummvm/commit/c425b690eba96777aca4af880f69e0f1d995daf4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:03+01:00
Commit Message:
MM: MM1: Fix display of market leaving messages
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/locations/location.cpp
engines/mm/mm1/views_enh/locations/location.h
engines/mm/mm1/views_enh/locations/market.cpp
engines/mm/mm1/views_enh/text_view.cpp
engines/mm/utils/strings.cpp
engines/mm/utils/strings.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 28b87c0b9ae..80bfdfd7347 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -303,6 +303,8 @@ enhdialogs:
gold: "gold"
market:
buy_food: "Buy food"
+ thankyou: "Thank you,\ncome again!"
+ no_gold: "No gold,\nno food!"
misc:
exit: "Exit"
stats:
diff --git a/engines/mm/mm1/views_enh/locations/location.cpp b/engines/mm/mm1/views_enh/locations/location.cpp
index 856eb03d2a0..728c1036669 100644
--- a/engines/mm/mm1/views_enh/locations/location.cpp
+++ b/engines/mm/mm1/views_enh/locations/location.cpp
@@ -39,6 +39,12 @@ void Location::leave() {
g_events->redraw();
}
+void Location::displayMessage(const Common::String &msg) {
+ Location::draw();
+
+ writeLine(3, msg, ALIGN_MIDDLE);
+}
+
} // namespace Locations
} // namespace ViewsEnh
} // namespace MM1
diff --git a/engines/mm/mm1/views_enh/locations/location.h b/engines/mm/mm1/views_enh/locations/location.h
index 9a5941aa49e..47bf07e7918 100644
--- a/engines/mm/mm1/views_enh/locations/location.h
+++ b/engines/mm/mm1/views_enh/locations/location.h
@@ -30,6 +30,14 @@ namespace ViewsEnh {
namespace Locations {
class Location : public ScrollView {
+protected:
+ /**
+ * Called when an active timeout countdown expired
+ */
+ void timeout() override {
+ leave();
+ }
+
public:
Location(const Common::String &name);
@@ -37,6 +45,11 @@ public:
* Leave the location, turning around
*/
void leave();
+
+ /**
+ * Display a message
+ */
+ void displayMessage(const Common::String &msg);
};
} // namespace Locations
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
index 831e09735e2..1b0aad3f269 100644
--- a/engines/mm/mm1/views_enh/locations/market.cpp
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -91,9 +91,9 @@ void Market::buyFood() {
}
clearSurface();
- writeString(10, 2, numPurchases ?
- STRING["dialogs.market.thankyou"] :
- STRING["dialogs.market.no_gold"]
+ displayMessage(numPurchases ?
+ STRING["enhdialogs.market.thankyou"] :
+ STRING["enhdialogs.market.no_gold"]
);
delaySeconds(3);
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 5a3f9fb68c5..aa148109af6 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -23,6 +23,7 @@
#include "mm/mm1/gfx/gfx.h"
#include "mm/mm1/views_enh/text_view.h"
#include "mm/mm1/mm1.h"
+#include "mm/utils/strings.h"
namespace MM {
namespace MM1 {
@@ -100,16 +101,23 @@ void TextView::writeString(int x, int y, const Common::String &str,
_textPos.x = x;
_textPos.y = y;
- if (align != ALIGN_LEFT && x == 0) {
- int strWidth = getFont()->getStringWidth(str);
+ Common::StringArray lines = splitLines(str);
- if (align == ALIGN_MIDDLE)
- _textPos.x = MAX((_innerBounds.width() - strWidth) / 2, 0);
- else
- _textPos.x = MAX(_innerBounds.width() - strWidth, 0);
- }
+ for (auto line : lines) {
+ if (line != lines.front())
+ newLine();
+
+ if (align != ALIGN_LEFT && x == 0) {
+ int strWidth = getFont()->getStringWidth(line);
- writeString(str);
+ if (align == ALIGN_MIDDLE)
+ _textPos.x = MAX((_innerBounds.width() - strWidth) / 2, 0);
+ else
+ _textPos.x = MAX(_innerBounds.width() - strWidth, 0);
+ }
+
+ writeString(line);
+ }
}
void TextView::writeNumber(int val) {
@@ -129,7 +137,7 @@ void TextView::writeLine(int lineNum, const Common::String &str,
void TextView::newLine() {
_textPos.x = 0;
- _textPos.y++;
+ _textPos.y += 8;
}
void TextView::clearSurface() {
diff --git a/engines/mm/utils/strings.cpp b/engines/mm/utils/strings.cpp
index ecd0df0a2ea..979a97ff905 100644
--- a/engines/mm/utils/strings.cpp
+++ b/engines/mm/utils/strings.cpp
@@ -113,4 +113,20 @@ int hexToInt(const Common::String &str) {
return (int)tmp;
}
+Common::StringArray splitLines(const Common::String &str) {
+ Common::StringArray results;
+ size_t start = 0, end;
+
+ while ((end = str.findFirstOf('\n', start)) != Common::String::npos) {
+ results.push_back(Common::String(
+ str.c_str() + start, str.c_str() + end));
+ start = end + 1;
+ }
+
+ results.push_back(str.c_str() + start);
+
+
+ return results;
+}
+
} // namespace MM
diff --git a/engines/mm/utils/strings.h b/engines/mm/utils/strings.h
index f39b734322a..83bf4e4adf1 100644
--- a/engines/mm/utils/strings.h
+++ b/engines/mm/utils/strings.h
@@ -23,6 +23,7 @@
#define MM_UTILS_STRINGS_H
#include "common/str.h"
+#include "common/str-array.h"
namespace MM {
@@ -32,6 +33,7 @@ extern Common::String searchAndReplace(const Common::String &str,
const Common::String &find, const Common::String &replace);
extern int strToInt(const Common::String &str);
extern int hexToInt(const Common::String &str);
+extern Common::StringArray splitLines(const Common::String &str);
} // namespace MM
Commit: 6b42ecb57fb0c7e988b454e4ab5c62e3543b00a5
https://github.com/scummvm/scummvm/commit/6b42ecb57fb0c7e988b454e4ab5c62e3543b00a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: Beginnings of temple location
Changed paths:
A engines/mm/mm1/views_enh/locations/temple.cpp
A engines/mm/mm1/views_enh/locations/temple.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/dialogs.h
engines/mm/mm1/views_enh/locations/location.cpp
engines/mm/mm1/views_enh/locations/location.h
engines/mm/mm1/views_enh/locations/market.cpp
engines/mm/mm1/views_enh/text_view.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 80bfdfd7347..b2b37558ea0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -298,15 +298,22 @@ enhdialogs:
conditions:
good: "Good"
location:
- store: "store"
- options: "options"
- gold: "gold"
+ store: "Store"
+ options: "Options"
+ options_for: "Options for"
+ gold: "Gold"
market:
buy_food: "Buy food"
thankyou: "Thank you,\ncome again!"
no_gold: "No gold,\nno food!"
misc:
exit: "Exit"
+ temple:
+ title: "Temple"
+ heal: "\x01""37Heal"
+ donate: "\x01""37Donate"
+ uncurse: "\x01""37Uncurse"
+ realign: "\x01""37Re-align"
stats:
none: "NONE"
inventory: "-----<EQUIPPED>----------<BACKPACK>----"
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index d4a758e9eef..4707d78ab7b 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -34,6 +34,7 @@
#include "mm/mm1/views_enh/character_info.h"
#include "mm/mm1/views_enh/game.h"
#include "mm/mm1/views_enh/locations/market.h"
+#include "mm/mm1/views_enh/locations/temple.h"
namespace MM {
namespace MM1 {
@@ -55,6 +56,7 @@ private:
// Views::ViewCharacters _viewCharacters;
// Views::ViewCharacter _viewCharacter;
ViewsEnh::Locations::Market _market;
+ ViewsEnh::Locations::Temple _temple;
public:
Dialogs() {}
};
diff --git a/engines/mm/mm1/views_enh/locations/location.cpp b/engines/mm/mm1/views_enh/locations/location.cpp
index 728c1036669..34052c734a7 100644
--- a/engines/mm/mm1/views_enh/locations/location.cpp
+++ b/engines/mm/mm1/views_enh/locations/location.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/views_enh/locations/location.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
#include "mm/utils/strings.h"
namespace MM {
@@ -45,6 +46,34 @@ void Location::displayMessage(const Common::String &msg) {
writeLine(3, msg, ALIGN_MIDDLE);
}
+void Location::changeCharacter(uint index) {
+ if (index >= g_globals->_party.size())
+ return;
+
+ g_globals->_currCharacter = &g_globals->_party[index];
+ redraw();
+}
+
+bool Location::subtractGold(uint amount) {
+ if (g_globals->_currCharacter->_gold < amount) {
+ notEnoughGold();
+ return false;
+ } else {
+ g_globals->_currCharacter->_gold -= amount;
+ return true;
+ }
+}
+
+void Location::notEnoughGold() {
+ Sound::sound(SOUND_2);
+ displayMessage(STRING["dialogs.misc.not_enough_gold"]);
+}
+
+void Location::backpackFull() {
+ Sound::sound(SOUND_2);
+ displayMessage(STRING["dialogs.misc.backpack_full"]);
+}
+
} // namespace Locations
} // namespace ViewsEnh
} // namespace MM1
diff --git a/engines/mm/mm1/views_enh/locations/location.h b/engines/mm/mm1/views_enh/locations/location.h
index 47bf07e7918..a1955d3330c 100644
--- a/engines/mm/mm1/views_enh/locations/location.h
+++ b/engines/mm/mm1/views_enh/locations/location.h
@@ -38,18 +38,38 @@ protected:
leave();
}
-public:
- Location(const Common::String &name);
+ /**
+ * Change character
+ */
+ virtual void changeCharacter(uint index);
/**
- * Leave the location, turning around
+ * Subtract gold from current character
*/
- void leave();
+ bool subtractGold(uint amount);
/**
* Display a message
*/
void displayMessage(const Common::String &msg);
+
+ /**
+ * Displays not enough gold
+ */
+ void notEnoughGold();
+
+ /**
+ * Displays backpack is full
+ */
+ void backpackFull();
+
+public:
+ Location(const Common::String &name);
+
+ /**
+ * Leave the location, turning around
+ */
+ void leave();
};
} // namespace Locations
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
index 1b0aad3f269..54bcc6a4562 100644
--- a/engines/mm/mm1/views_enh/locations/market.cpp
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -90,7 +90,6 @@ void Market::buyFood() {
++numPurchases;
}
- clearSurface();
displayMessage(numPurchases ?
STRING["enhdialogs.market.thankyou"] :
STRING["enhdialogs.market.no_gold"]
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
new file mode 100644
index 00000000000..e4408429450
--- /dev/null
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -0,0 +1,228 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/locations/Temple.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+#include "mm/utils/strings.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+namespace Locations {
+
+Temple::Temple() : Location("Temple") {
+ addButton(&g_globals->_confirmIcons,
+ Common::Point(_innerBounds.width() / 2 - 24,
+ _innerBounds.height() - 32),
+ 0, Common::KEYCODE_y);
+}
+
+bool Temple::msgFocus(const FocusMessage &msg) {
+ send("View", ValueMessage(LOC_TEMPLE));
+ changeCharacter(0);
+
+ return true;
+}
+
+void Temple::draw() {
+ Location::draw();
+
+ writeLine(0, STRING["enhdialogs.temple.title"], ALIGN_MIDDLE);
+ writeLine(1, STRING["enhdialogs.location.options_for"], ALIGN_MIDDLE);
+ writeLine(3, camelCase(g_globals->_currCharacter->_name), ALIGN_MIDDLE);
+
+ setReduced(true);
+ writeLine(5, STRING["enhdialogs.temple.heal"]);
+ writeLine(6, STRING["enhdialogs.temple.uncurse"]);
+ writeLine(7, STRING["enhdialogs.temple.realign"]);
+ writeLine(8, STRING["enhdialogs.temple.donate"]);
+
+ writeLine(5, _healCost ?
+ Common::String::format("%d", _healCost).c_str() : "----",
+ ALIGN_RIGHT);
+ writeLine(6, _uncurseCost ?
+ Common::String::format("%d", _uncurseCost).c_str() : "----",
+ ALIGN_RIGHT);
+ writeLine(7, _alignmentCost ?
+ Common::String::format("%d", _alignmentCost).c_str() : "----",
+ ALIGN_RIGHT);
+ writeLine(8, Common::String::format("%d", _donateCost).c_str(),
+ ALIGN_RIGHT);
+ setReduced(false);
+
+ writeLine(10, STRING["enhdialogs.location.gold"]);
+ writeLine(10, Common::String::format("%d",
+ g_globals->_currCharacter->_gold), ALIGN_RIGHT);
+}
+
+bool Temple::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ leave();
+ break;
+ case Common::KEYCODE_h:
+ restoreHealth();
+ break;
+ case Common::KEYCODE_u:
+ uncurseItems();
+ break;
+ case Common::KEYCODE_r:
+ restoreAlignment();
+ break;
+ case Common::KEYCODE_d:
+ donate();
+ break;
+ case Common::KEYCODE_g:
+ g_globals->_currCharacter->gatherGold();
+ redraw();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ changeCharacter(msg.keycode - Common::KEYCODE_1);
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Temple::changeCharacter(uint index) {
+ Maps::Map &map = *g_maps->_currentMap;
+ int i;
+
+ if (index >= g_globals->_party.size())
+ return;
+ Location::changeCharacter(index);
+
+ _isEradicated = false;
+
+ int townNum = map[0];
+ if (townNum < 1 || townNum >= 6)
+ townNum = 1;
+ --townNum;
+
+ Character &c = *g_globals->_currCharacter;
+
+ _healCost = 0;
+ if (c._condition == ERADICATED) {
+ _healCost = HEAL_COST1[townNum];
+ _isEradicated = true;
+ } else if (c._condition & BAD_CONDITION) {
+ _healCost = HEAL_COST2[townNum];
+ } else if (c._condition || c._hp < c._hpMax) {
+ _healCost = HEAL_COST3[townNum];
+ }
+
+ _uncurseCost = UNCURSE_COST[townNum];
+ for (i = 0; i < INVENTORY_COUNT; ++i) {
+ if (c._equipped[i]) {
+ if (getItem(c._equipped[i])->_equipMode == EQUIP_CURSED)
+ break;
+ }
+ }
+ if (i == INVENTORY_COUNT)
+ _uncurseCost = 0;
+
+ _alignmentCost = ALIGNMENT_COST[townNum];
+ if (c._alignment == c._alignmentInitial)
+ _alignmentCost = 0;
+
+ _donateCost = DONATE_COST[townNum];
+}
+
+void Temple::restoreHealth() {
+ if (subtractGold(_healCost)) {
+ Character &c = *g_globals->_currCharacter;
+ c._condition = FINE;
+ c._hpBase = c._hp;
+
+ if (_isEradicated) {
+ c._age._current += 10;
+ --c._endurance;
+ }
+
+ redraw();
+ }
+}
+
+void Temple::uncurseItems() {
+ if (subtractGold(_uncurseCost)) {
+ Character &c = *g_globals->_currCharacter;
+ for (int i = 0; i < INVENTORY_COUNT; ++i) {
+ if (c._equipped[i]) {
+ getItem(c._equipped[i]);
+ if (g_globals->_currItem._equipMode == EQUIP_CURSED) {
+ c._equipped.removeAt(i);
+ --i;
+ }
+ }
+ }
+
+ redraw();
+ }
+}
+
+void Temple::restoreAlignment() {
+ if (subtractGold(_alignmentCost)) {
+ Character &c = *g_globals->_currCharacter;
+ c._alignment = c._alignmentInitial;
+ c._v6f = ALIGNMENT_VALS[c._alignment];
+
+ redraw();
+ }
+}
+
+void Temple::donate() {
+ if (subtractGold(_donateCost)) {
+ Maps::Map &map = *g_maps->_currentMap;
+ Character &c = *g_globals->_currCharacter;
+
+ int townNum = map[0];
+ if (townNum < 1 || townNum >= 6)
+ townNum = 1;
+ --townNum;
+
+ c._v6e |= DONATE_VALS[townNum];
+ draw();
+
+ if (g_engine->getRandomNumber(15) == 10) {
+ for (int i = 0; i < 13; ++i)
+ g_globals->_spells._arr[i] = 75;
+
+ Sound::sound(SOUND_3);
+ displayMessage(STRING["dialogs.temple.protected"]);
+ } else {
+ displayMessage(STRING["dialogs.temple.thankyou"]);
+ }
+ }
+}
+
+} // namespace Location
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/locations/temple.h b/engines/mm/mm1/views_enh/locations/temple.h
new file mode 100644
index 00000000000..4c18480699b
--- /dev/null
+++ b/engines/mm/mm1/views_enh/locations/temple.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_LOCATIONS_TEMPLE_H
+#define MM1_VIEWS_ENH_LOCATIONS_TEMPLE_H
+
+#include "mm/mm1/views_enh/locations/location.h"
+#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/locations.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+namespace Locations {
+
+class Temple : public Location, public TempleData {
+private:
+ bool _isEradicated = false;
+ int _healCost = 0, _uncurseCost = 0;
+ int _alignmentCost = 0, _donateCost = 0;
+private:
+ void restoreHealth();
+ void uncurseItems();
+ void restoreAlignment();
+ void donate();
+
+protected:
+ /**
+ * Change character
+ */
+ void changeCharacter(uint index) override;
+
+public:
+ Temple();
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Locations
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index aa148109af6..191354435df 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -29,6 +29,8 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
+#define ROW_HEIGHT 9
+
TextView::TextView(const Common::String &name) :
UIElement(name, g_engine) {
}
@@ -132,12 +134,12 @@ void TextView::writeNumber(int x, int y, int val) {
void TextView::writeLine(int lineNum, const Common::String &str,
TextAlign align, int xp) {
- writeString(xp, lineNum * 8, str, align);
+ writeString(xp, lineNum * ROW_HEIGHT, str, align);
}
void TextView::newLine() {
_textPos.x = 0;
- _textPos.y += 8;
+ _textPos.y += ROW_HEIGHT;
}
void TextView::clearSurface() {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 2215fa4d615..555440deecf 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -72,6 +72,7 @@ MODULE_OBJS := \
mm1/views_enh/text_view.o \
mm1/views_enh/locations/location.o \
mm1/views_enh/locations/market.o \
+ mm1/views_enh/locations/temple.o \
mm1/maps/maps.o \
mm1/maps/map.o \
mm1/maps/map00.o \
Commit: d0817fc3a5e9be90fb2d118b1b094919821ae6ca
https://github.com/scummvm/scummvm/commit/d0817fc3a5e9be90fb2d118b1b094919821ae6ca
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: Change char.cpp to character.cpp
Changed paths:
A engines/mm/mm1/data/character.cpp
A engines/mm/mm1/data/character.h
R engines/mm/mm1/data/char.cpp
R engines/mm/mm1/data/char.h
engines/mm/mm1/data/game_state.h
engines/mm/mm1/data/party.h
engines/mm/mm1/data/roster.h
engines/mm/mm1/views/locations/market.h
engines/mm/mm1/views/locations/training.h
engines/mm/mm1/views_enh/locations/market.h
engines/mm/mm1/views_enh/locations/temple.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/char.cpp b/engines/mm/mm1/data/character.cpp
similarity index 99%
rename from engines/mm/mm1/data/char.cpp
rename to engines/mm/mm1/data/character.cpp
index 623cb054c0c..306011e2431 100644
--- a/engines/mm/mm1/data/char.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -20,7 +20,7 @@
*/
#include "common/algorithm.h"
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/mm1.h"
namespace MM {
diff --git a/engines/mm/mm1/data/char.h b/engines/mm/mm1/data/character.h
similarity index 100%
rename from engines/mm/mm1/data/char.h
rename to engines/mm/mm1/data/character.h
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index ad4667e72f9..ab301c57009 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -25,7 +25,7 @@
#include "common/array.h"
#include "common/rect.h"
#include "common/serializer.h"
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/data/party.h"
#include "mm/mm1/data/spells.h"
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index e0690d705d2..396b3211696 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -23,7 +23,7 @@
#define MM1_DATA_PARTY_H
#include "common/array.h"
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
namespace MM {
namespace MM1 {
diff --git a/engines/mm/mm1/data/roster.h b/engines/mm/mm1/data/roster.h
index 90dacf095da..8ca594a7619 100644
--- a/engines/mm/mm1/data/roster.h
+++ b/engines/mm/mm1/data/roster.h
@@ -23,7 +23,7 @@
#define MM1_DATA_ROSTER_H
#include "common/serializer.h"
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/maps/maps.h"
namespace MM {
diff --git a/engines/mm/mm1/views/locations/market.h b/engines/mm/mm1/views/locations/market.h
index 63eae4f1ec7..a23319f1691 100644
--- a/engines/mm/mm1/views/locations/market.h
+++ b/engines/mm/mm1/views/locations/market.h
@@ -22,7 +22,7 @@
#ifndef MM1_VIEWS_LOCATIONS_MARKET_H
#define MM1_VIEWS_LOCATIONS_MARKET_H
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/views/locations/location.h"
#include "mm/mm1/data/locations.h"
diff --git a/engines/mm/mm1/views/locations/training.h b/engines/mm/mm1/views/locations/training.h
index b3375c0c072..565c0e3e7d8 100644
--- a/engines/mm/mm1/views/locations/training.h
+++ b/engines/mm/mm1/views/locations/training.h
@@ -22,7 +22,7 @@
#ifndef MM1_VIEWS_LOCATIONS_TRAINING_H
#define MM1_VIEWS_LOCATIONS_TRAINING_H
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/views/locations/location.h"
#include "mm/mm1/data/locations.h"
diff --git a/engines/mm/mm1/views_enh/locations/market.h b/engines/mm/mm1/views_enh/locations/market.h
index a123dedad37..3399ccd2aca 100644
--- a/engines/mm/mm1/views_enh/locations/market.h
+++ b/engines/mm/mm1/views_enh/locations/market.h
@@ -23,7 +23,7 @@
#define MM1_VIEWS_ENH_LOCATIONS_MARKET_H
#include "mm/mm1/views_enh/locations/location.h"
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/data/locations.h"
namespace MM {
diff --git a/engines/mm/mm1/views_enh/locations/temple.h b/engines/mm/mm1/views_enh/locations/temple.h
index 4c18480699b..9b578c7e2f1 100644
--- a/engines/mm/mm1/views_enh/locations/temple.h
+++ b/engines/mm/mm1/views_enh/locations/temple.h
@@ -23,7 +23,7 @@
#define MM1_VIEWS_ENH_LOCATIONS_TEMPLE_H
#include "mm/mm1/views_enh/locations/location.h"
-#include "mm/mm1/data/char.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/data/locations.h"
namespace MM {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 555440deecf..149aee6b378 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -14,7 +14,7 @@ MODULE_OBJS := \
mm1/meta_engine.o \
mm1/mm1.o \
mm1/sound.o \
- mm1/data/char.o \
+ mm1/data/character.o \
mm1/data/game_state.o \
mm1/data/items.o \
mm1/data/party.o \
Commit: b03e0feb5a7c4f40ef0b21e57481a0aaf6001b97
https://github.com/scummvm/scummvm/commit/b03e0feb5a7c4f40ef0b21e57481a0aaf6001b97
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: Further implementation of spelling casting
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/data/spells.h
engines/mm/mm1/views/character_info.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b2b37558ea0..76683208c18 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -248,7 +248,13 @@
no_characters: "NO AVAILABLE CHARACTERS"
some_characters: "AVAILABLE CHARACTERS"
not_enough_gold: "*** NOT ENOUGH GOLD ***"
+ not_enough_gems: "*** NOT ENOUGH GEMS ***"
+ not_enough_sp: "*** NOT ENOUGH SPELL POINTS ***"
+ combat_only: "*** COMBAT ONLY ***
+ magic_doesnt_work: "*** MAGIC DOESN'T WORK HERE ***"
+ outdoors_only: "*** OUTDOOR ONLY ***"
full: "*** BACKPACK FULL ***"
+ done: "*** DONE ***"
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 306011e2431..778046b8558 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -30,25 +30,45 @@ static const int CLASS_HP_PER_LEVEL[6] = {
12, 10, 10, 8, 6, 8
};
-static const int8 SPELLS_SP[2][47] = {
- {
- 0, 0, 0, 0, 0, -1, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0, 2, 0, 2, 2,
- 0, 0, 0, 3, 3,
- 4, 4, 4, 4, 4,
- 10, 5, 5, 5, 5
- },
- {
- 0, 0, -1, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 0, 0,
- -1, 0, 1, -1, 0, 0, 1, 0,
- 0, 0, 2, 0, 0, 2, 2, 2,
- 0, 0, 3, 3, 3,
- 4, 4, 4, 4, 4,
- 5, 100, 5, 5, 5
- }
+static const int8 SPELLS_SP_GEMS[47 * 2] = {
+ 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 2, 0, 2, 2,
+ 0, 0, 0, 3, 3,
+ 4, 4, 4, 4, 4,
+ 10, 5, 5, 5, 5,
+
+ 0, 0, -1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0,
+ -1, 0, 1, -1, 0, 0, 1, 0,
+ 0, 0, 2, 0, 0, 2, 2, 2,
+ 0, 0, 3, 3, 3,
+ 4, 4, 4, 4, 4,
+ 5, 100, 5, 5, 5
+};
+
+static const byte SPELL_FLAGS[47 * 2] = {
+ 1, 1, 9, 4, 2, 4, 0, 1,
+ 4, 5, 9, 0, 0, 0, 9, 9,
+ 2, 4, 4, 2, 9, 9, 2, 2,
+ 6, 6, 0, 0, 6, 25, 5, 2,
+ 17, 0, 1, 4, 4,
+ 17, 4, 6, 4, 2,
+ 1, 1, 0, 6, 25,
+
+ 1, 2, 9, 9, 0, 2, 2, 9,
+ 9, 9, 9, 2, 2, 5, 5, 9,
+ 9, 18, 1, 9, 1, 1, 1, 9,
+ 9, 9, 9, 9, 2, 0, 1, 1,
+ 17, 0, 9, 2, 2,
+ 1, 9, 2, 0, 2,
+ 2, 2, 17, 1, 1
+};
+
+enum SpellFlag {
+ SF_COMBAT_ONLY = 1,
+ SF_OUTDOORS_ONLY = 0x10
};
void Inventory::clear() {
@@ -130,10 +150,10 @@ void Character::synchronize(Common::Serializer &s) {
_age.synchronize(s);
s.syncAsUint32LE(_exp);
- s.syncAsByte(_sp._base);
- s.skip(1);
s.syncAsByte(_sp._current);
- s.skip(1);
+ s.syncAsByte(_v2c);
+ s.syncAsByte(_sp._base);
+ s.syncAsByte(_v2e);
_slvl.synchronize(s);
s.syncAsUint16LE(_gems);
@@ -403,7 +423,7 @@ Common::String Character::getConditionString() const {
return result;
}
-void Character::castSpell(int lvl, int num) {
+SpellResult Character::castSpell(int lvl, int num) {
int lvlNum;
int setNum = _class == ARCHER || _class == SORCERER ? 1 : 0;
@@ -415,11 +435,41 @@ void Character::castSpell(int lvl, int num) {
spellNum += 5;
// Get required SP
- int requiredSp = SPELLS_SP[setNum][spellNum];
- if (requiredSp < 0)
+ int spellIndex = setNum * 47 + spellNum;
+ int requiredSp = lvl - 1;
+
+ if (SPELLS_SP_GEMS[spellIndex] < 0)
// required SP increases with character's level
requiredSp = _level;
+ if (!_v2c) {
+ if (SPELLS_SP_GEMS[spellIndex] < 0 && _sp._current < _level._current)
+ return SR_NOT_ENOUGH_SP;
+ if ((lvl - 1) > _sp._current)
+ return SR_NOT_ENOUGH_SP;
+ }
+
+ int requiredGems = (uint8)SPELLS_SP_GEMS[spellIndex] & 0x7f;
+ if (requiredGems && requiredGems > _gems)
+ return SR_NOT_ENOUGH_GEMS;
+
+ return performSpell(spellNum, requiredSp, requiredGems);
+}
+
+SpellResult Character::performSpell(int spellIndex, int requiredSp, int baseSp) {
+ const Maps::Map &map = *g_maps->_currentMap;
+
+ if (SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
+ return SR_COMBAT_ONLY;
+ if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) && !(map[0] & 0x80))
+ return SR_OUTDOORS_ONLY;
+
+ // TODO: Selection of cast on
+
+ return SR_OK;
+}
+
+void Character::cast2() {
}
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 46645349281..d5e17ffe362 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -56,6 +56,12 @@ enum Condition {
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
};
+enum SpellResult {
+ SR_OK, SR_NOT_ENOUGH_SP, SR_NOT_ENOUGH_GEMS,
+ SR_COMBAT_ONLY, SR_DOESNT_WORK,
+ SR_MAGIC_DOESNT_WORK, SR_OUTDOORS_ONLY
+};
+
class Inventory {
public:
struct Entry {
@@ -186,6 +192,8 @@ struct Character {
AttributePair _slvl;
AttributePair _ac;
+ byte _v2c = 0;
+ byte _v2e = 0;
uint32 _exp = 0;
uint16 _gems = 0;
uint16 _hpBase = 0, _hp = 0, _hpMax = 0;
@@ -260,7 +268,14 @@ struct Character {
/**
* Cast a spell
*/
- void castSpell(int lvl, int num);
+ SpellResult castSpell(int lvl, int num);
+
+ /**
+ * Inner handler to perform a spell
+ */
+ SpellResult performSpell(int spellIndex, int requiredSp, int baseSp);
+
+ void cast2();
/**
* Gets a character's condition string
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 9135e9c272d..f185859d3c9 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -54,7 +54,7 @@ struct ItemData {
EquipMode _equipMode;
byte _val10;
byte _val11;
- byte _val12;
+ byte _spellId;
byte _val13;
uint16 _cost;
byte _val16;
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
index 02442269226..eaa85afb870 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/data/spells.h
@@ -56,6 +56,10 @@ union ActiveSpells {
byte _arr[ACTIVE_SPELLS_COUNT];
};
+class Spells {
+public:
+ static void cast() {}
+};
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 6cda3992718..e2492f985cf 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -571,7 +571,40 @@ void CharacterInfo::spellNumberEntered(uint num) {
return;
}
- g_globals->_currCharacter->castSpell(_spellLevel, num);
+ Common::String msg;
+ int xp;
+ switch (g_globals->_currCharacter->castSpell(_spellLevel, num)) {
+ case SR_NOT_ENOUGH_SP:
+ msg = STRING["dialogs.misc.not_enough_sp"];
+ xp = 5;
+ break;
+ case SR_NOT_ENOUGH_GEMS:
+ msg = STRING["dialogs.misc.not_enough_gems"];
+ xp = 9;
+ break;
+ case SR_COMBAT_ONLY:
+ msg = STRING["dialogs.misc.combat_only"];
+ xp = 10;
+ break;
+ case SR_DOESNT_WORK:
+ msg = STRING["dialogs.misc.magic_doesnt_work"];
+ xp = 5;
+ break;
+ case SR_OUTDOORS_ONLY:
+ msg = STRING["dialogs.misc.outdoors_only"];
+ xp = 10;
+ break;
+ default:
+ msg = STRING["dialogs.misc.done"];
+ xp = 14;
+ break;
+ }
+
+ Sound::sound(SOUND_2);
+ clearSurface();
+ writeString(5, 21, msg);
+ _state = DISPLAY;
+ delaySeconds(3);
}
} // namespace ViewsEnh
Commit: d2dd3253d6ed07b480233ad141b62dd65170c99f
https://github.com/scummvm/scummvm/commit/d2dd3253d6ed07b480233ad141b62dd65170c99f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: In progress new view for spell casting
Changed paths:
A engines/mm/mm1/game/spell_casting.cpp
A engines/mm/mm1/game/spell_casting.h
A engines/mm/mm1/views/cast_spell.cpp
A engines/mm/mm1/views/cast_spell.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 76683208c18..9d9dd3d0099 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -255,6 +255,7 @@
outdoors_only: "*** OUTDOOR ONLY ***"
full: "*** BACKPACK FULL ***"
done: "*** DONE ***"
+ enter_to_cast: "'ENTER' TO CAST"
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 778046b8558..d8e88a1a9ee 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -30,47 +30,6 @@ static const int CLASS_HP_PER_LEVEL[6] = {
12, 10, 10, 8, 6, 8
};
-static const int8 SPELLS_SP_GEMS[47 * 2] = {
- 0, 0, 0, 0, 0, -1, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0, 2, 0, 2, 2,
- 0, 0, 0, 3, 3,
- 4, 4, 4, 4, 4,
- 10, 5, 5, 5, 5,
-
- 0, 0, -1, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 0, 0,
- -1, 0, 1, -1, 0, 0, 1, 0,
- 0, 0, 2, 0, 0, 2, 2, 2,
- 0, 0, 3, 3, 3,
- 4, 4, 4, 4, 4,
- 5, 100, 5, 5, 5
-};
-
-static const byte SPELL_FLAGS[47 * 2] = {
- 1, 1, 9, 4, 2, 4, 0, 1,
- 4, 5, 9, 0, 0, 0, 9, 9,
- 2, 4, 4, 2, 9, 9, 2, 2,
- 6, 6, 0, 0, 6, 25, 5, 2,
- 17, 0, 1, 4, 4,
- 17, 4, 6, 4, 2,
- 1, 1, 0, 6, 25,
-
- 1, 2, 9, 9, 0, 2, 2, 9,
- 9, 9, 9, 2, 2, 5, 5, 9,
- 9, 18, 1, 9, 1, 1, 1, 9,
- 9, 9, 9, 9, 2, 0, 1, 1,
- 17, 0, 9, 2, 2,
- 1, 9, 2, 0, 2,
- 2, 2, 17, 1, 1
-};
-
-enum SpellFlag {
- SF_COMBAT_ONLY = 1,
- SF_OUTDOORS_ONLY = 0x10
-};
-
void Inventory::clear() {
_items.clear();
_items.resize(INVENTORY_COUNT);
@@ -239,7 +198,6 @@ Character::TradeResult Character::trade(int whoTo, int itemIndex) {
return TRADE_SUCCESS;
}
-
Character::LevelIncrease Character::increaseLevel() {
++_level;
++_age;
@@ -423,55 +381,5 @@ Common::String Character::getConditionString() const {
return result;
}
-SpellResult Character::castSpell(int lvl, int num) {
- int lvlNum;
- int setNum = _class == ARCHER || _class == SORCERER ? 1 : 0;
-
- // Figure the offset in the spell list
- int spellNum = 0;
- for (lvlNum = 2; lvlNum < MIN(lvl, 5); ++lvlNum)
- spellNum += 8;
- for (lvlNum = 5; lvlNum < lvl; ++lvlNum)
- spellNum += 5;
-
- // Get required SP
- int spellIndex = setNum * 47 + spellNum;
- int requiredSp = lvl - 1;
-
- if (SPELLS_SP_GEMS[spellIndex] < 0)
- // required SP increases with character's level
- requiredSp = _level;
-
- if (!_v2c) {
- if (SPELLS_SP_GEMS[spellIndex] < 0 && _sp._current < _level._current)
- return SR_NOT_ENOUGH_SP;
- if ((lvl - 1) > _sp._current)
- return SR_NOT_ENOUGH_SP;
- }
-
- int requiredGems = (uint8)SPELLS_SP_GEMS[spellIndex] & 0x7f;
- if (requiredGems && requiredGems > _gems)
- return SR_NOT_ENOUGH_GEMS;
-
- return performSpell(spellNum, requiredSp, requiredGems);
-}
-
-SpellResult Character::performSpell(int spellIndex, int requiredSp, int baseSp) {
- const Maps::Map &map = *g_maps->_currentMap;
-
- if (SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
- return SR_COMBAT_ONLY;
- if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) && !(map[0] & 0x80))
- return SR_OUTDOORS_ONLY;
-
- // TODO: Selection of cast on
-
- return SR_OK;
-}
-
-void Character::cast2() {
-
-}
-
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index d5e17ffe362..913bb32efb5 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -56,12 +56,6 @@ enum Condition {
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
};
-enum SpellResult {
- SR_OK, SR_NOT_ENOUGH_SP, SR_NOT_ENOUGH_GEMS,
- SR_COMBAT_ONLY, SR_DOESNT_WORK,
- SR_MAGIC_DOESNT_WORK, SR_OUTDOORS_ONLY
-};
-
class Inventory {
public:
struct Entry {
@@ -265,18 +259,6 @@ struct Character {
*/
void updateAC();
- /**
- * Cast a spell
- */
- SpellResult castSpell(int lvl, int num);
-
- /**
- * Inner handler to perform a spell
- */
- SpellResult performSpell(int spellIndex, int requiredSp, int baseSp);
-
- void cast2();
-
/**
* Gets a character's condition string
*/
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
new file mode 100644
index 00000000000..656c2d5a8af
--- /dev/null
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -0,0 +1,147 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/game/spell_casting.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+static const int8 SPELLS_SP_GEMS[47 * 2] = {
+ 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 2, 0, 2, 2,
+ 0, 0, 0, 3, 3,
+ 4, 4, 4, 4, 4,
+ 10, 5, 5, 5, 5,
+
+ 0, 0, -1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0,
+ -1, 0, 1, -1, 0, 0, 1, 0,
+ 0, 0, 2, 0, 0, 2, 2, 2,
+ 0, 0, 3, 3, 3,
+ 4, 4, 4, 4, 4,
+ 5, 100, 5, 5, 5
+};
+
+static const byte SPELL_FLAGS[47 * 2] = {
+ 1, 1, 9, 4, 2, 4, 0, 1,
+ 4, 5, 9, 0, 0, 0, 9, 9,
+ 2, 4, 4, 2, 9, 9, 2, 2,
+ 6, 6, 0, 0, 6, 25, 5, 2,
+ 17, 0, 1, 4, 4,
+ 17, 4, 6, 4, 2,
+ 1, 1, 0, 6, 25,
+
+ 1, 2, 9, 9, 0, 2, 2, 9,
+ 9, 9, 9, 2, 2, 5, 5, 9,
+ 9, 18, 1, 9, 1, 1, 1, 9,
+ 9, 9, 9, 9, 2, 0, 1, 1,
+ 17, 0, 9, 2, 2,
+ 1, 9, 2, 0, 2,
+ 2, 2, 17, 1, 1
+};
+
+enum SpellFlag {
+ SF_COMBAT_ONLY = 1,
+ SF_CAST_ON = 4,
+ SF_OUTDOORS_ONLY = 0x10
+};
+
+void SpellCasting::setSpell(Character *chr, int lvl, int num) {
+ int lvlNum;
+ int setNum = chr->_class == ARCHER || chr->_class == SORCERER ? 1 : 0;
+ _spellState = SS_OK;
+
+ // Figure the offset in the spell list
+ int spellNum = 0;
+ for (lvlNum = 2; lvlNum < MIN(lvl, 5); ++lvlNum)
+ spellNum += 8;
+ for (lvlNum = 5; lvlNum < lvl; ++lvlNum)
+ spellNum += 5;
+
+ // Get required SP
+ int spellIndex = setNum * 47 + spellNum;
+ int requiredSp = lvl - 1;
+
+ if (SPELLS_SP_GEMS[spellIndex] < 0)
+ // required SP increases with character's level
+ requiredSp = chr->_level;
+
+ if (!chr->_v2c) {
+ if (SPELLS_SP_GEMS[spellIndex] < 0 && chr->_sp._current < chr->_level._current)
+ _spellState = SS_NOT_ENOUGH_SP;
+ else if ((lvl - 1) > chr->_sp._current)
+ _spellState = SS_NOT_ENOUGH_SP;
+ }
+
+ int requiredGems = (uint8)SPELLS_SP_GEMS[spellIndex] & 0x7f;
+ if (_spellState == SS_OK)
+ setSpell(spellIndex, requiredSp, requiredGems);
+}
+
+void SpellCasting::setSpell(int spellIndex, int requiredSp, int requiredGems) {
+ _spellIndex = spellIndex;
+ _requiredSp = requiredSp;
+ _requiredGems = requiredGems;
+ _spellState = SS_OK;
+
+ Maps::Map &map = *g_maps->_currentMap;
+
+ if (SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
+ _spellState = SS_COMBAT_ONLY;
+ else if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) && !(map[0] & 0x80))
+ _spellState = SS_OUTDOORS_ONLY;
+ else if (g_maps->_currentState & 2)
+ _spellState = SS_MAGIC_DOESNT_WORK;
+}
+
+bool SpellCasting::hasCharTarget() const {
+ return (SPELL_FLAGS[_spellIndex] & SF_CAST_ON) != 0;
+}
+
+Common::String SpellCasting::getSpellError() const {
+ switch (_spellState) {
+ case SS_NOT_ENOUGH_SP:
+ return STRING["dialogs.misc.not_enough_sp"];
+ case SS_NOT_ENOUGH_GEMS:
+ return STRING["dialogs.misc.not_enough_gems"];
+ case SS_COMBAT_ONLY:
+ return STRING["dialogs.misc.combat_only"];
+ case SS_DOESNT_WORK:
+ return STRING["dialogs.misc.magic_doesnt_work"];
+ case SS_OUTDOORS_ONLY:
+ return STRING["dialogs.misc.outdoors_only"];
+ default:
+ return STRING["dialogs.misc.done"];
+ }
+}
+
+void SpellCasting::castSpell(int spellIndex, Character *destChar) {
+ // TODO
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/spell_casting.h b/engines/mm/mm1/game/spell_casting.h
new file mode 100644
index 00000000000..221bd540b54
--- /dev/null
+++ b/engines/mm/mm1/game/spell_casting.h
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_SPELL_CASTING_H
+#define MM1_GAME_SPELL_CASTING_H
+
+#include "mm/mm1/data/character.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+enum SpellState {
+ SS_OK, SS_NOT_ENOUGH_SP, SS_NOT_ENOUGH_GEMS,
+ SS_COMBAT_ONLY, SS_DOESNT_WORK,
+ SS_MAGIC_DOESNT_WORK, SS_OUTDOORS_ONLY
+};
+
+/**
+ * Support class for handling spell casting logic
+ */
+class SpellCasting {
+protected:
+ int _spellIndex = 0;
+ int _requiredSp = 0, _requiredGems = 0;
+ SpellState _spellState = SS_OK;
+public:
+ /**
+ * Sets the current spell
+ */
+ void setSpell(Character *chr, int lvl, int num);
+
+ /**
+ * Sets a spell directly by index
+ */
+ void setSpell(int spellIndex, int requiredSp, int requiredGems);
+
+ /**
+ * Returns true if the spell requires a target
+ */
+ bool hasCharTarget() const;
+
+ /**
+ * Returns true if a spell can be cast
+ */
+ bool canCast() const {
+ return _spellState == SS_OK;
+ }
+
+ /**
+ * Returns the spell error
+ */
+ SpellState getSpellState() const {
+ return _spellState;
+ }
+
+ /**
+ * Returns the error message
+ */
+ Common::String getSpellError() const;
+
+ /**
+ * Actually cast the spell
+ */
+ void castSpell(int spellIndex, Character *destChar = nullptr);
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/cast_spell.cpp
new file mode 100644
index 00000000000..e262798a16d
--- /dev/null
+++ b/engines/mm/mm1/views/cast_spell.cpp
@@ -0,0 +1,162 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/cast_spell.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+CastSpell::CastSpell() : TextView("CastSpell") {
+ _bounds = getLineBounds(21, 24);
+}
+
+bool CastSpell::msgValue(const ValueMessage &msg) {
+ if (msg._value == 0) {
+ // Ensure current character can cast spells
+ if (g_globals->_currCharacter->_slvl != 0 &&
+ g_globals->_currCharacter->_sp != 0) {
+ startCasting();
+ }
+ } else {
+ // Spell bound to an item
+ setSpell(msg._value, 0, 0);
+
+ if (canCast()) {
+ _state = STATE_ENTER;
+ } else {
+ spellDone();
+ }
+ }
+
+ return true;
+}
+
+void CastSpell::startCasting() {
+ clearLines(20, 24);
+ escToGoBack(0);
+ writeString(7, 20, STRING["dialogs.character.cast_spell"]);
+
+ _textEntry.display(27, 20, 1, true,
+ []() {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->close();
+ },
+ [](const Common::String &text) {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->spellLevelEntered(atoi(text.c_str()));
+ }
+ );
+}
+
+void CastSpell::spellLevelEntered(uint level) {
+ // Ensure the spell level is valid
+ if (level < 1 || level > 7 ||
+ level > g_globals->_currCharacter->_slvl) {
+ redraw();
+ return;
+ }
+
+ clearLines(21, 21);
+ writeString(19, 21, STRING["dialogs.character.number"]);
+
+ _textEntry.display(27, 21, 1, true,
+ []() {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->close();
+ },
+ [](const Common::String &text) {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->spellNumberEntered(atoi(text.c_str()));
+ }
+ );
+}
+
+void CastSpell::spellNumberEntered(uint num) {
+ if (num < 1 || num > 8 || (_spellLevel >= 5 && num >= 6)) {
+ close();
+ return;
+ }
+
+ setSpell(g_globals->_currCharacter, _spellLevel, num);
+ if (!canCast())
+ spellDone();
+ else if (hasCharTarget())
+ _state = STATE_SELECT_CHAR;
+ else
+ _state = STATE_ENTER;
+
+ draw();
+}
+
+void CastSpell::draw() {
+ if (_state == STATE_ENTER) {
+ clearSurface();
+ writeString(24, 23, STRING["dialogs.misc.enter_to_cast"]);
+ }
+}
+
+bool CastSpell::msgKeypress(const KeypressMessage &msg) {
+ if (_state == STATE_ENTER) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ } else if (msg.keycode == Common::KEYCODE_RETURN) {
+ // Time to execute the spell
+ Character &c = *g_globals->_currCharacter;
+ c._sp._current = MAX(c._sp._current - _requiredSp, 0);
+ c._gems = MAX(c._gems - _requiredGems, 0);
+
+ }
+ }
+
+ return true;
+}
+
+void CastSpell::timeout() {
+ close();
+}
+
+void CastSpell::spellDone() {
+ Common::String msg = getSpellError();
+ int xp = 5;
+
+ switch (getSpellState()) {
+ case Game::SS_NOT_ENOUGH_GEMS: xp = 9; break;
+ case Game::SS_COMBAT_ONLY: xp = 10; break;
+ case Game::SS_OUTDOORS_ONLY: xp = 10; break;
+ default: break;
+ }
+
+ Sound::sound(SOUND_2);
+ clearSurface();
+ writeString(xp, 21, msg);
+ delaySeconds(3);
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/cast_spell.h b/engines/mm/mm1/views/cast_spell.h
new file mode 100644
index 00000000000..e24abe54832
--- /dev/null
+++ b/engines/mm/mm1/views/cast_spell.h
@@ -0,0 +1,75 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_CAST_SPELL_H
+#define MM1_VIEWS_CAST_SPELL_H
+
+#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/text_entry.h"
+#include "mm/mm1/game/spell_casting.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class CastSpell : public TextView, public MM1::Game::SpellCasting {
+ enum State {
+ STATE_INITIAL, STATE_SELECT_CHAR, STATE_ENTER
+ };
+private:
+ State _state = STATE_INITIAL;
+ TextEntry _textEntry;
+ int _spellLevel = -1;
+private:
+ /**
+ * Start the selection of spell to cast
+ */
+ void startCasting();
+
+ /**
+ * Spell level number entered
+ */
+ void spellLevelEntered(uint level);
+
+ /**
+ * Spell number entered
+ */
+ void spellNumberEntered(uint num);
+
+ /**
+ * Spell done or failed
+ */
+ void spellDone();
+public:
+ CastSpell();
+ virtual ~CastSpell() {}
+
+ bool msgValue(const ValueMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void timeout() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index e2492f985cf..a8db5f1af4d 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -113,7 +113,7 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case DISPLAY:
switch (msg.keycode) {
case Common::KEYCODE_c:
- castSpell();
+ send("CastSpell", ValueMessage(0));
break;
case Common::KEYCODE_e:
if (!g_globals->_currCharacter->_backpack.empty())
@@ -514,98 +514,6 @@ void CharacterInfo::tradeHowMuch() {
);
}
-void CharacterInfo::castSpell() {
- if (g_globals->_currCharacter->_slvl == 0 ||
- g_globals->_currCharacter->_sp == 0) {
- // Character can't cast spells, so exit
- redraw();
- return;
- }
-
- clearLines(20, 24);
- escToGoBack(0);
- writeString(7, 20, STRING["dialogs.character.cast_spell"]);
-
- _textEntry.display(27, 20, 1, true,
- []() {
- CharacterInfo *view =
- (CharacterInfo *)g_events->focusedView();
- view->redraw();
- },
- [](const Common::String &text) {
- CharacterInfo *view =
- (CharacterInfo *)g_events->focusedView();
- view->spellLevelEntered(atoi(text.c_str()));
- }
- );
-}
-
-void CharacterInfo::spellLevelEntered(uint level) {
- // Ensure the spell level is valid
- if (level < 1 || level > 7 ||
- level > g_globals->_currCharacter->_slvl) {
- redraw();
- return;
- }
-
- clearLines(21, 21);
- writeString(19, 21, STRING["dialogs.character.number"]);
-
- _textEntry.display(27, 21, 1, true,
- []() {
- CharacterInfo *view =
- (CharacterInfo *)g_events->focusedView();
- view->redraw();
- },
- [](const Common::String &text) {
- CharacterInfo *view =
- (CharacterInfo *)g_events->focusedView();
- view->spellNumberEntered(atoi(text.c_str()));
- }
- );
-}
-
-void CharacterInfo::spellNumberEntered(uint num) {
- if (num < 1 || num > 8 || (_spellLevel >= 5 && num >= 6)) {
- redraw();
- return;
- }
-
- Common::String msg;
- int xp;
- switch (g_globals->_currCharacter->castSpell(_spellLevel, num)) {
- case SR_NOT_ENOUGH_SP:
- msg = STRING["dialogs.misc.not_enough_sp"];
- xp = 5;
- break;
- case SR_NOT_ENOUGH_GEMS:
- msg = STRING["dialogs.misc.not_enough_gems"];
- xp = 9;
- break;
- case SR_COMBAT_ONLY:
- msg = STRING["dialogs.misc.combat_only"];
- xp = 10;
- break;
- case SR_DOESNT_WORK:
- msg = STRING["dialogs.misc.magic_doesnt_work"];
- xp = 5;
- break;
- case SR_OUTDOORS_ONLY:
- msg = STRING["dialogs.misc.outdoors_only"];
- xp = 10;
- break;
- default:
- msg = STRING["dialogs.misc.done"];
- xp = 14;
- break;
- }
-
- Sound::sound(SOUND_2);
- clearSurface();
- writeString(5, 21, msg);
- _state = DISPLAY;
- delaySeconds(3);
-}
} // namespace ViewsEnh
} // namespace MM1
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 4cbb13935d4..4fa9ef321b8 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -45,7 +45,6 @@ private:
int _tradeWith = -1;
TransferKind _tradeKind = TK_GEMS;
TextEntry _textEntry;
- int _spellLevel = -1;
private:
/**
* Equips the item at the given index
@@ -67,10 +66,6 @@ private:
*/
void tradeHowMuch();
- /**
- * Starts selection of a spell to cast
- */
- void castSpell();
public:
CharacterInfo() : CharacterBase("CharacterInfo") {}
@@ -89,19 +84,8 @@ public:
* How much entered for a trade
*/
void howMuchEntered(uint amount);
-
- /**
- * Spell level entered for casting
- */
- void spellLevelEntered(uint level);
-
- /**
- * Spell number within the level entered for casting
- */
- void spellNumberEntered(uint num);
};
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index d2a1fc00fa1..069c5806b63 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -32,6 +32,7 @@
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
+#include "mm/mm1/views/cast_spell.h"
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/encounter.h"
@@ -50,6 +51,7 @@ namespace Views {
struct Dialogs {
private:
Views::AreYouReady _areYouReady;
+ Views::CastSpell _castSpell;
Views::CreateCharacters _createCharacters;
Views::Encounter _encounter;
Views::Game _game;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 149aee6b378..1764f49aa96 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -21,6 +21,7 @@ MODULE_OBJS := \
mm1/data/roster.o \
mm1/data/spells.o \
mm1/game/search.o \
+ mm1/game/spell_casting.o \
mm1/game/view_base.o \
mm1/gfx/dta.o \
mm1/gfx/gfx.o \
@@ -41,6 +42,7 @@ MODULE_OBJS := \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
mm1/views/are_you_ready.o \
+ mm1/views/cast_spell.o \
mm1/views/character_base.o \
mm1/views/character_info.o \
mm1/views/character_manage.o \
Commit: 639e6ddbcca57e220138210841ab11edbedf2180
https://github.com/scummvm/scummvm/commit/639e6ddbcca57e220138210841ab11edbedf2180
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: Further fixes for spell casting view
Changed paths:
engines/mm/mm1/views/cast_spell.cpp
engines/mm/mm1/views/cast_spell.h
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/cast_spell.cpp
index e262798a16d..7a5811ed78f 100644
--- a/engines/mm/mm1/views/cast_spell.cpp
+++ b/engines/mm/mm1/views/cast_spell.cpp
@@ -28,7 +28,7 @@ namespace MM1 {
namespace Views {
CastSpell::CastSpell() : TextView("CastSpell") {
- _bounds = getLineBounds(21, 24);
+ _bounds = getLineBounds(20, 24);
}
bool CastSpell::msgValue(const ValueMessage &msg) {
@@ -36,14 +36,16 @@ bool CastSpell::msgValue(const ValueMessage &msg) {
// Ensure current character can cast spells
if (g_globals->_currCharacter->_slvl != 0 &&
g_globals->_currCharacter->_sp != 0) {
- startCasting();
+ addView();
+ setState(SELECT_SPELL);
}
} else {
// Spell bound to an item
+ addView();
setSpell(msg._value, 0, 0);
if (canCast()) {
- _state = STATE_ENTER;
+ setState(PRESS_ENTER);
} else {
spellDone();
}
@@ -52,48 +54,75 @@ bool CastSpell::msgValue(const ValueMessage &msg) {
return true;
}
-void CastSpell::startCasting() {
- clearLines(20, 24);
- escToGoBack(0);
- writeString(7, 20, STRING["dialogs.character.cast_spell"]);
-
- _textEntry.display(27, 20, 1, true,
- []() {
- CastSpell *view =
- (CastSpell *)g_events->focusedView();
- view->close();
- },
- [](const Common::String &text) {
- CastSpell *view =
- (CastSpell *)g_events->focusedView();
- view->spellLevelEntered(atoi(text.c_str()));
- }
+void CastSpell::setState(State state) {
+ _state = state;
+
+ MetaEngine::setKeybindingMode(
+ _state == SELECT_CHAR ?
+ KeybindingMode::KBMODE_PARTY_MENUS :
+ KeybindingMode::KBMODE_MENUS
+ );
+ draw();
+}
+
+void CastSpell::draw() {
+ switch (_state) {
+ case SELECT_SPELL:
+ clearSurface();
+ escToGoBack(0);
+ writeString(7, 0, STRING["dialogs.character.cast_spell"]);
+
+ _textEntry.display(27, 20, 1, true,
+ []() {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->close();
+ },
+ [](const Common::String &text) {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->spellLevelEntered(atoi(text.c_str()));
+ }
+ );
+ break;
+
+ case SELECT_NUMBER:
+ clearLines(1, 1);
+ writeString(19, 1, STRING["dialogs.character.number"]);
+
+ _textEntry.display(27, 21, 1, true,
+ []() {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->close();
+ },
+ [](const Common::String &text) {
+ CastSpell *view =
+ (CastSpell *)g_events->focusedView();
+ view->spellNumberEntered(atoi(text.c_str()));
+ }
);
+ break;
+
+ case PRESS_ENTER:
+ clearSurface();
+ writeString(24, 3, STRING["dialogs.misc.enter_to_cast"]);
+ break;
+
+ default:
+ break;
+ }
}
void CastSpell::spellLevelEntered(uint level) {
// Ensure the spell level is valid
if (level < 1 || level > 7 ||
level > g_globals->_currCharacter->_slvl) {
- redraw();
+ close();
return;
}
- clearLines(21, 21);
- writeString(19, 21, STRING["dialogs.character.number"]);
-
- _textEntry.display(27, 21, 1, true,
- []() {
- CastSpell *view =
- (CastSpell *)g_events->focusedView();
- view->close();
- },
- [](const Common::String &text) {
- CastSpell *view =
- (CastSpell *)g_events->focusedView();
- view->spellNumberEntered(atoi(text.c_str()));
- }
- );
+ setState(SELECT_NUMBER);
}
void CastSpell::spellNumberEntered(uint num) {
@@ -106,22 +135,15 @@ void CastSpell::spellNumberEntered(uint num) {
if (!canCast())
spellDone();
else if (hasCharTarget())
- _state = STATE_SELECT_CHAR;
+ _state = SELECT_CHAR;
else
- _state = STATE_ENTER;
+ _state = PRESS_ENTER;
draw();
}
-void CastSpell::draw() {
- if (_state == STATE_ENTER) {
- clearSurface();
- writeString(24, 23, STRING["dialogs.misc.enter_to_cast"]);
- }
-}
-
bool CastSpell::msgKeypress(const KeypressMessage &msg) {
- if (_state == STATE_ENTER) {
+ if (_state == PRESS_ENTER) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
close();
} else if (msg.keycode == Common::KEYCODE_RETURN) {
@@ -130,6 +152,7 @@ bool CastSpell::msgKeypress(const KeypressMessage &msg) {
c._sp._current = MAX(c._sp._current - _requiredSp, 0);
c._gems = MAX(c._gems - _requiredGems, 0);
+ // TODO: Cast the spell
}
}
@@ -151,6 +174,7 @@ void CastSpell::spellDone() {
default: break;
}
+ _state = ENDING;
Sound::sound(SOUND_2);
clearSurface();
writeString(xp, 21, msg);
diff --git a/engines/mm/mm1/views/cast_spell.h b/engines/mm/mm1/views/cast_spell.h
index e24abe54832..4046aacc1e4 100644
--- a/engines/mm/mm1/views/cast_spell.h
+++ b/engines/mm/mm1/views/cast_spell.h
@@ -32,13 +32,19 @@ namespace Views {
class CastSpell : public TextView, public MM1::Game::SpellCasting {
enum State {
- STATE_INITIAL, STATE_SELECT_CHAR, STATE_ENTER
+ SELECT_SPELL, SELECT_NUMBER, SELECT_CHAR, PRESS_ENTER,
+ ENDING
};
private:
- State _state = STATE_INITIAL;
+ State _state = SELECT_SPELL;
TextEntry _textEntry;
int _spellLevel = -1;
private:
+ /**
+ * Set the current state
+ */
+ void setState(State state);
+
/**
* Start the selection of spell to cast
*/
Commit: 7fd9a034812feed456266d6964b08f227e0d3535
https://github.com/scummvm/scummvm/commit/7fd9a034812feed456266d6964b08f227e0d3535
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: Hide cursor after finishing text entry
Changed paths:
engines/mm/mm1/views/text_entry.cpp
engines/mm/mm1/views/text_entry.h
diff --git a/engines/mm/mm1/views/text_entry.cpp b/engines/mm/mm1/views/text_entry.cpp
index ff91a94e672..b7de04bd8f3 100644
--- a/engines/mm/mm1/views/text_entry.cpp
+++ b/engines/mm/mm1/views/text_entry.cpp
@@ -39,22 +39,27 @@ void TextEntry::display(int x, int y, int maxLen,
}
void TextEntry::draw() {
+ drawText();
+ writeChar('_');
+}
+
+void TextEntry::drawText() {
clearSurface();
writeString(_text);
- writeChar('_');
}
bool TextEntry::msgKeypress(const KeypressMessage &msg) {
Common::KeyCode kc = msg.keycode;
if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ drawText();
close();
_abortFn();
return true;
} else if (msg.keycode == Common::KEYCODE_BACKSPACE &&
!_text.empty()) {
_text.deleteLastChar();
- redraw();
+ drawText();
return true;
} else if (msg.ascii >= 32 && msg.ascii <= 127 &&
_text.size() < _maxLen) {
@@ -62,7 +67,7 @@ bool TextEntry::msgKeypress(const KeypressMessage &msg) {
return true;
_text += msg.ascii;
- redraw();
+ drawText();
// Single character numeric fields, particular spell
// level/number selection, return immediately
@@ -71,6 +76,7 @@ bool TextEntry::msgKeypress(const KeypressMessage &msg) {
}
if (kc == Common::KEYCODE_RETURN && !_text.empty()) {
+ drawText();
close();
_enterFn(_text);
return true;
diff --git a/engines/mm/mm1/views/text_entry.h b/engines/mm/mm1/views/text_entry.h
index 2cfc0302235..a1faddeb373 100644
--- a/engines/mm/mm1/views/text_entry.h
+++ b/engines/mm/mm1/views/text_entry.h
@@ -32,6 +32,12 @@ namespace Views {
* Text or numeric entry.
*/
class TextEntry : public TextView {
+private:
+ /**
+ * Draw the entered text
+ */
+ void drawText();
+
public:
typedef void (*Abort)();
typedef void (*Enter)(const Common::String &text);
Commit: 75276b13f00bb211e608d64b45703b2681526903
https://github.com/scummvm/scummvm/commit/75276b13f00bb211e608d64b45703b2681526903
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: Cast spell selection working
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/game/spell_casting.h
engines/mm/mm1/views/cast_spell.cpp
engines/mm/mm1/views/cast_spell.h
engines/mm/mm1/views/text_entry.cpp
engines/mm/mm1/views/text_view.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9d9dd3d0099..5933aed5f1f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -250,12 +250,13 @@
not_enough_gold: "*** NOT ENOUGH GOLD ***"
not_enough_gems: "*** NOT ENOUGH GEMS ***"
not_enough_sp: "*** NOT ENOUGH SPELL POINTS ***"
- combat_only: "*** COMBAT ONLY ***
+ combat_only: "*** COMBAT ONLY ***"
magic_doesnt_work: "*** MAGIC DOESN'T WORK HERE ***"
outdoors_only: "*** OUTDOOR ONLY ***"
full: "*** BACKPACK FULL ***"
done: "*** DONE ***"
enter_to_cast: "'ENTER' TO CAST"
+ cast_on: "CAST ON: '1'-'%d'?"
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index d8e88a1a9ee..cdb39b3e691 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -381,5 +381,9 @@ Common::String Character::getConditionString() const {
return result;
}
+void Character::castUnknown() {
+ warning("TODO: castUnknown method");
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 913bb32efb5..b096b8c08fd 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -263,6 +263,8 @@ struct Character {
* Gets a character's condition string
*/
Common::String getConditionString() const;
+
+ void castUnknown();
};
} // namespace MM1
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index aaed71179d2..50c8fe99964 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -58,5 +58,10 @@ uint Party::getPartyGold() const {
return total;
}
+void Party::updateAC() {
+ for (uint i = 0; i < size(); ++i)
+ (*this)[i].updateAC();
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index 396b3211696..30d3d07406c 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -38,6 +38,11 @@ struct Party : public Common::Array<Character> {
* Get the party gold combined
*/
uint getPartyGold() const;
+
+ /**
+ * Update the entire party AC
+ */
+ void updateAC();
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 656c2d5a8af..861bf56e1e8 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -75,7 +75,7 @@ void SpellCasting::setSpell(Character *chr, int lvl, int num) {
_spellState = SS_OK;
// Figure the offset in the spell list
- int spellNum = 0;
+ int spellNum = num - 1;
for (lvlNum = 2; lvlNum < MIN(lvl, 5); ++lvlNum)
spellNum += 8;
for (lvlNum = 5; lvlNum < lvl; ++lvlNum)
@@ -113,12 +113,15 @@ void SpellCasting::setSpell(int spellIndex, int requiredSp, int requiredGems) {
_spellState = SS_COMBAT_ONLY;
else if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) && !(map[0] & 0x80))
_spellState = SS_OUTDOORS_ONLY;
- else if (g_maps->_currentState & 2)
- _spellState = SS_MAGIC_DOESNT_WORK;
}
bool SpellCasting::hasCharTarget() const {
- return (SPELL_FLAGS[_spellIndex] & SF_CAST_ON) != 0;
+ return true; //**DEBUG**
+ //return (SPELL_FLAGS[_spellIndex] & SF_CAST_ON) != 0;
+}
+
+bool SpellCasting::isMagicAllowed() const {
+ return !(g_maps->_currentState & 2);
}
Common::String SpellCasting::getSpellError() const {
@@ -129,8 +132,6 @@ Common::String SpellCasting::getSpellError() const {
return STRING["dialogs.misc.not_enough_gems"];
case SS_COMBAT_ONLY:
return STRING["dialogs.misc.combat_only"];
- case SS_DOESNT_WORK:
- return STRING["dialogs.misc.magic_doesnt_work"];
case SS_OUTDOORS_ONLY:
return STRING["dialogs.misc.outdoors_only"];
default:
@@ -138,8 +139,9 @@ Common::String SpellCasting::getSpellError() const {
}
}
-void SpellCasting::castSpell(int spellIndex, Character *destChar) {
+void SpellCasting::castSpell(Character *destChar) {
// TODO
+ error("TODO: cast");
}
} // namespace Game
diff --git a/engines/mm/mm1/game/spell_casting.h b/engines/mm/mm1/game/spell_casting.h
index 221bd540b54..4a2aae88d96 100644
--- a/engines/mm/mm1/game/spell_casting.h
+++ b/engines/mm/mm1/game/spell_casting.h
@@ -30,8 +30,7 @@ namespace Game {
enum SpellState {
SS_OK, SS_NOT_ENOUGH_SP, SS_NOT_ENOUGH_GEMS,
- SS_COMBAT_ONLY, SS_DOESNT_WORK,
- SS_MAGIC_DOESNT_WORK, SS_OUTDOORS_ONLY
+ SS_COMBAT_ONLY, SS_DOESNT_WORK, SS_OUTDOORS_ONLY
};
/**
@@ -59,12 +58,18 @@ public:
bool hasCharTarget() const;
/**
- * Returns true if a spell can be cast
+ * Returns true if a spell can be cast, with the exception
+ * of magic not being allowed at the current location.
*/
bool canCast() const {
return _spellState == SS_OK;
}
+ /**
+ * Returns if magic is allowed at the current location
+ */
+ bool isMagicAllowed() const;
+
/**
* Returns the spell error
*/
@@ -80,7 +85,7 @@ public:
/**
* Actually cast the spell
*/
- void castSpell(int spellIndex, Character *destChar = nullptr);
+ void castSpell(Character *destChar = nullptr);
};
} // namespace Game
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/cast_spell.cpp
index 7a5811ed78f..2406569c1c8 100644
--- a/engines/mm/mm1/views/cast_spell.cpp
+++ b/engines/mm/mm1/views/cast_spell.cpp
@@ -44,10 +44,12 @@ bool CastSpell::msgValue(const ValueMessage &msg) {
addView();
setSpell(msg._value, 0, 0);
- if (canCast()) {
- setState(PRESS_ENTER);
- } else {
+ if (!canCast()) {
spellDone();
+ } else if (hasCharTarget()) {
+ setState(SELECT_CHAR);
+ } else {
+ setState(PRESS_ENTER);
}
}
@@ -104,6 +106,13 @@ void CastSpell::draw() {
);
break;
+ case SELECT_CHAR:
+ writeString(22, 3, Common::String::format(
+ STRING["dialogs.misc.cast_on"].c_str(),
+ (int)g_globals->_party.size()
+ ));
+ break;
+
case PRESS_ENTER:
clearSurface();
writeString(24, 3, STRING["dialogs.misc.enter_to_cast"]);
@@ -135,34 +144,66 @@ void CastSpell::spellNumberEntered(uint num) {
if (!canCast())
spellDone();
else if (hasCharTarget())
- _state = SELECT_CHAR;
+ setState(SELECT_CHAR);
else
- _state = PRESS_ENTER;
+ setState(PRESS_ENTER);
draw();
}
bool CastSpell::msgKeypress(const KeypressMessage &msg) {
- if (_state == PRESS_ENTER) {
- if (msg.keycode == Common::KEYCODE_ESCAPE) {
- close();
- } else if (msg.keycode == Common::KEYCODE_RETURN) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+ } else if (_state == PRESS_ENTER) {
+ if (msg.keycode == Common::KEYCODE_RETURN) {
// Time to execute the spell
- Character &c = *g_globals->_currCharacter;
- c._sp._current = MAX(c._sp._current - _requiredSp, 0);
- c._gems = MAX(c._gems - _requiredGems, 0);
-
- // TODO: Cast the spell
+ performSpell();
}
}
return true;
}
+bool CastSpell::msgAction(const ActionMessage &msg) {
+ if (_state == SELECT_CHAR &&
+ msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ uint charIndex = (int)(msg._action - KEYBIND_VIEW_PARTY1);
+ if (charIndex < g_globals->_party.size())
+ performSpell(&g_globals->_party[charIndex]);
+ }
+
+ return true;
+}
+
+
void CastSpell::timeout() {
close();
}
+void CastSpell::performSpell(Character *chr) {
+ Character &c = *g_globals->_currCharacter;
+ c._sp._current = MAX(c._sp._current - _requiredSp, 0);
+ c._gems = MAX(c._gems - _requiredGems, 0);
+
+ c.castUnknown();
+
+ if (!isMagicAllowed()) {
+ spellDone(STRING["dialogs.misc.magic_doesnt_work"], 5);
+ } else {
+ // Cast the spell
+ castSpell(chr);
+
+ // Display spell done
+ clearSurface();
+ writeString(14, 2, STRING["dialogs.misc.done"]);
+ Sound::sound(SOUND_2);
+
+ g_globals->_party.updateAC();
+ delaySeconds(3);
+ }
+}
+
void CastSpell::spellDone() {
Common::String msg = getSpellError();
int xp = 5;
@@ -174,10 +215,14 @@ void CastSpell::spellDone() {
default: break;
}
+ spellDone(msg, xp);
+}
+
+void CastSpell::spellDone(const Common::String &msg, int xp) {
_state = ENDING;
Sound::sound(SOUND_2);
clearSurface();
- writeString(xp, 21, msg);
+ writeString(xp, 1, msg);
delaySeconds(3);
}
diff --git a/engines/mm/mm1/views/cast_spell.h b/engines/mm/mm1/views/cast_spell.h
index 4046aacc1e4..50ff89d31b6 100644
--- a/engines/mm/mm1/views/cast_spell.h
+++ b/engines/mm/mm1/views/cast_spell.h
@@ -45,11 +45,6 @@ private:
*/
void setState(State state);
- /**
- * Start the selection of spell to cast
- */
- void startCasting();
-
/**
* Spell level number entered
*/
@@ -60,10 +55,16 @@ private:
*/
void spellNumberEntered(uint num);
+ /**
+ * Cast the spell
+ */
+ void performSpell(Character *chr = nullptr);
+
/**
* Spell done or failed
*/
void spellDone();
+ void spellDone(const Common::String &msg, int xp);
public:
CastSpell();
virtual ~CastSpell() {}
@@ -71,6 +72,7 @@ public:
bool msgValue(const ValueMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
void timeout() override;
};
diff --git a/engines/mm/mm1/views/text_entry.cpp b/engines/mm/mm1/views/text_entry.cpp
index b7de04bd8f3..ef0b6bc0447 100644
--- a/engines/mm/mm1/views/text_entry.cpp
+++ b/engines/mm/mm1/views/text_entry.cpp
@@ -63,7 +63,7 @@ bool TextEntry::msgKeypress(const KeypressMessage &msg) {
return true;
} else if (msg.ascii >= 32 && msg.ascii <= 127 &&
_text.size() < _maxLen) {
- if (_isNumeric && (msg.ascii <= '0' || msg.ascii >= '9'))
+ if (_isNumeric && (msg.ascii < '0' || msg.ascii > '9'))
return true;
_text += msg.ascii;
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 1c62330fcb6..dbf11db5a8a 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -124,7 +124,8 @@ void TextView::drawTextBorder() {
}
void TextView::escToGoBack(int x) {
- writeString(x, 24, STRING["dialogs.misc.go_back"]);
+ writeString(x, (_bounds.height() / FONT_SIZE) - 1,
+ STRING["dialogs.misc.go_back"]);
}
void TextView::timeout() {
Commit: f9bc0360997a1e5e1a6097b87ed97cdbfb4fbdf5
https://github.com/scummvm/scummvm/commit/f9bc0360997a1e5e1a6097b87ed97cdbfb4fbdf5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:04+01:00
Commit Message:
MM: MM1: Light spell now working
Changed paths:
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/data/spells.h
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/game/spell_casting.h
engines/mm/mm1/views/cast_spell.cpp
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 28d057ccc87..d5afe236cfa 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -25,5 +25,28 @@
namespace MM {
namespace MM1 {
+Spells::SpellFn Spells::SPELLS[SPELLS_COUNT] = {
+ // Cleric spells
+ placeholder,
+ placeholder,
+ placeholder,
+ spell04_firstAid,
+ spell05_light
+};
+
+void Spells::cast(int spell, Character *chr) {
+ assert(spell < SPELLS_COUNT);
+ SPELLS[spell](chr);
+}
+
+void Spells::spell04_firstAid(Character *chr) {
+
+}
+
+void Spells::spell05_light(Character *chr) {
+ g_globals->_spells._s.light++;
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
index eaa85afb870..e85d7073cf3 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/data/spells.h
@@ -22,12 +22,13 @@
#ifndef MM1_DATA_SPELLS_H
#define MM1_DATA_SPELLS_H
-#include "common/scummsys.h"
+#include "mm/mm1/data/character.h"
namespace MM {
namespace MM1 {
-
+//define SPELLS_COUNT (47 * 2)
+#define SPELLS_COUNT 5
#define ACTIVE_SPELLS_COUNT 18
struct ActiveSpellsStruct {
@@ -57,8 +58,15 @@ union ActiveSpells {
};
class Spells {
+ typedef void (*SpellFn)(Character *chr);
+private:
+ static void placeholder(Character *chr) {}
+ static void spell04_firstAid(Character *chr);
+ static void spell05_light(Character *chr);
+
+ static SpellFn SPELLS[SPELLS_COUNT];
public:
- static void cast() {}
+ static void cast(int spell, Character *chr);
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 861bf56e1e8..e398eeae091 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -116,8 +116,7 @@ void SpellCasting::setSpell(int spellIndex, int requiredSp, int requiredGems) {
}
bool SpellCasting::hasCharTarget() const {
- return true; //**DEBUG**
- //return (SPELL_FLAGS[_spellIndex] & SF_CAST_ON) != 0;
+ return (SPELL_FLAGS[_spellIndex] & SF_CAST_ON) != 0;
}
bool SpellCasting::isMagicAllowed() const {
@@ -139,11 +138,6 @@ Common::String SpellCasting::getSpellError() const {
}
}
-void SpellCasting::castSpell(Character *destChar) {
- // TODO
- error("TODO: cast");
-}
-
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spell_casting.h b/engines/mm/mm1/game/spell_casting.h
index 4a2aae88d96..d27c49929de 100644
--- a/engines/mm/mm1/game/spell_casting.h
+++ b/engines/mm/mm1/game/spell_casting.h
@@ -81,11 +81,6 @@ public:
* Returns the error message
*/
Common::String getSpellError() const;
-
- /**
- * Actually cast the spell
- */
- void castSpell(Character *destChar = nullptr);
};
} // namespace Game
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/cast_spell.cpp
index 2406569c1c8..1e63e7bd6f8 100644
--- a/engines/mm/mm1/views/cast_spell.cpp
+++ b/engines/mm/mm1/views/cast_spell.cpp
@@ -131,6 +131,7 @@ void CastSpell::spellLevelEntered(uint level) {
return;
}
+ _spellLevel = level;
setState(SELECT_NUMBER);
}
@@ -192,7 +193,7 @@ void CastSpell::performSpell(Character *chr) {
spellDone(STRING["dialogs.misc.magic_doesnt_work"], 5);
} else {
// Cast the spell
- castSpell(chr);
+ Spells::cast(_spellIndex, chr);
// Display spell done
clearSurface();
Commit: 3c0bf90c4150ddcc411161310a7108101ccb9957
https://github.com/scummvm/scummvm/commit/3c0bf90c4150ddcc411161310a7108101ccb9957
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: Added stubs for all non-combat spells
Changed paths:
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/data/spells.h
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index d5afe236cfa..a75ab14cc08 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -30,23 +30,158 @@ Spells::SpellFn Spells::SPELLS[SPELLS_COUNT] = {
placeholder,
placeholder,
placeholder,
- spell04_firstAid,
- spell05_light
+ cleric14_firstAid,
+ cleric15_light,
+ cleric16_powerCure,
+ cleric17_protectionFromFear,
+ placeholder,
+ cleric21_cureWounds,
+ placeholder,
+ placeholder,
+ cleric24_protectionFromCold,
+ cleric25_protectionFromIce,
+ cleric26_protectionFromPoison,
+ placeholder,
+ placeholder,
+ cleric31_createFood,
+ cleric32_cureBlindness,
+ cleric33_cureParalysis,
+ cleric34_lastingLight,
+ placeholder,
+ placeholder,
+ cleric37_removeQuest,
+ cleric38_walkOnWater,
+ cleric41_cureDisease,
+ cleric42_neutralizePoison,
+ cleric43_protectionFromAcid,
+ cleric44_protectionFromElectricity,
+ cleric45_restoreAlignment,
+ placeholder,
+ placeholder,
+ cleric48_surface,
+ placeholder,
+ cleric52_dispelMagic,
+ placeholder,
+ cleric54_removeCondition,
+ cleric55_restoreEnergy,
+ placeholder,
+ cleric62_raiseDead,
+ cleric63_rejuvinate,
+ cleric64_stoneToFlesh,
+ cleric65_townPortal,
+ placeholder,
+ placeholder,
+ cleric73_protectionFromElements,
+ cleric74_resurrection,
+ placeholder,
+
+ placeholder,
+ wizard12_detectMagic,
+ placeholder,
+ placeholder,
+ wizard15_leatherSkin,
+ wizard16_light,
+ wizard17_location,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ wizard24_jump,
+ wizard25_levitate,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ wizard32_fly,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ placeholder,
+ wizard45_guardDog,
+ wizard46_psychicProtection,
+ placeholder,
+ placeholder,
+ placeholder,
+ wizard52_dispelMagic,
+ placeholder,
+ wizard54_shelter,
+ wizard55_teleport,
+ placeholder,
+ placeholder,
+ wizard63_etherialize,
+ wizard64_protectionFromMagic,
+ wizard65_rechargeItem,
+ wizard71_astralSpell,
+ wizard72_duplication,
+ placeholder,
+ placeholder,
+ placeholder,
};
-void Spells::cast(int spell, Character *chr) {
+bool Spells::cast(int spell, Character *chr) {
assert(spell < SPELLS_COUNT);
- SPELLS[spell](chr);
+ return SPELLS[spell](chr);
}
-void Spells::spell04_firstAid(Character *chr) {
-
+bool Spells::cleric14_firstAid(Character *chr) {
+ return true;
}
-void Spells::spell05_light(Character *chr) {
+bool Spells::cleric15_light(Character *chr) {
g_globals->_spells._s.light++;
g_events->send("Game", GameMessage("UPDATE"));
+ return true;
}
+bool Spells::cleric16_powerCure(Character *chr) { return false; }
+bool Spells::cleric17_protectionFromFear(Character *chr) { return false; }
+bool Spells::cleric21_cureWounds(Character *chr) { return false; }
+bool Spells::cleric24_protectionFromCold(Character *chr) { return false; }
+bool Spells::cleric25_protectionFromIce(Character *chr) { return false; }
+bool Spells::cleric26_protectionFromPoison(Character *chr) { return false; }
+bool Spells::cleric31_createFood(Character *chr) { return false; }
+bool Spells::cleric32_cureBlindness(Character *chr) { return false; }
+bool Spells::cleric33_cureParalysis(Character *chr) { return false; }
+bool Spells::cleric34_lastingLight(Character *chr) { return false; }
+bool Spells::cleric37_removeQuest(Character *chr) { return false; }
+bool Spells::cleric38_walkOnWater(Character *chr) { return false; }
+bool Spells::cleric41_cureDisease(Character *chr) { return false; }
+bool Spells::cleric42_neutralizePoison(Character *chr) { return false; }
+bool Spells::cleric43_protectionFromAcid(Character *chr) { return false; }
+bool Spells::cleric44_protectionFromElectricity(Character *chr) { return false; }
+bool Spells::cleric45_restoreAlignment(Character *chr) { return false; }
+bool Spells::cleric48_surface(Character *chr) { return false; }
+bool Spells::cleric52_dispelMagic(Character *chr) { return false; }
+bool Spells::cleric54_removeCondition(Character *chr) { return false; }
+bool Spells::cleric55_restoreEnergy(Character *chr) { return false; }
+bool Spells::cleric62_raiseDead(Character *chr) { return false; }
+bool Spells::cleric63_rejuvinate(Character *chr) { return false; }
+bool Spells::cleric64_stoneToFlesh(Character *chr) { return false; }
+bool Spells::cleric65_townPortal(Character *chr) { return false; }
+bool Spells::cleric73_protectionFromElements(Character *chr) { return false; }
+bool Spells::cleric74_resurrection(Character *chr) { return false; }
+
+bool Spells::wizard12_detectMagic(Character *chr) { return false; }
+bool Spells::wizard15_leatherSkin(Character *chr) { return false; }
+bool Spells::wizard17_location(Character *chr) { return false; }
+bool Spells::wizard24_jump(Character *chr) { return false; }
+bool Spells::wizard25_levitate(Character *chr) { return false; }
+bool Spells::wizard32_fly(Character *chr) { return false; }
+bool Spells::wizard45_guardDog(Character *chr) { return false; }
+bool Spells::wizard46_psychicProtection(Character *chr) { return false; }
+bool Spells::wizard54_shelter(Character *chr) { return false; }
+bool Spells::wizard55_teleport(Character *chr) { return false; }
+bool Spells::wizard63_etherialize(Character *chr) { return false; }
+bool Spells::wizard64_protectionFromMagic(Character *chr) { return false; }
+bool Spells::wizard65_rechargeItem(Character *chr) { return false; }
+bool Spells::wizard71_astralSpell(Character *chr) { return false; }
+bool Spells::wizard72_duplication(Character *chr) { return false; }
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
index e85d7073cf3..19dc1a6a2af 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/data/spells.h
@@ -27,8 +27,7 @@
namespace MM {
namespace MM1 {
-//define SPELLS_COUNT (47 * 2)
-#define SPELLS_COUNT 5
+#define SPELLS_COUNT (47 * 2)
#define ACTIVE_SPELLS_COUNT 18
struct ActiveSpellsStruct {
@@ -58,15 +57,69 @@ union ActiveSpells {
};
class Spells {
- typedef void (*SpellFn)(Character *chr);
+ typedef bool (*SpellFn)(Character *chr);
private:
- static void placeholder(Character *chr) {}
- static void spell04_firstAid(Character *chr);
- static void spell05_light(Character *chr);
+ static bool placeholder(Character *chr) { return false; }
+ static bool cleric14_firstAid(Character *chr);
+ static bool cleric15_light(Character *chr);
+ static bool cleric16_powerCure(Character *chr);
+ static bool cleric17_protectionFromFear(Character *chr);
+ static bool cleric21_cureWounds(Character *chr);
+ static bool cleric24_protectionFromCold(Character *chr);
+ static bool cleric25_protectionFromIce(Character *chr);
+ static bool cleric26_protectionFromPoison(Character *chr);
+ static bool cleric31_createFood(Character *chr);
+ static bool cleric32_cureBlindness(Character *chr);
+ static bool cleric33_cureParalysis(Character *chr);
+ static bool cleric34_lastingLight(Character *chr);
+ static bool cleric37_removeQuest(Character *chr);
+ static bool cleric38_walkOnWater(Character *chr);
+ static bool cleric41_cureDisease(Character *chr);
+ static bool cleric42_neutralizePoison(Character *chr);
+ static bool cleric43_protectionFromAcid(Character *chr);
+ static bool cleric44_protectionFromElectricity(Character *chr);
+ static bool cleric45_restoreAlignment(Character *chr);
+ static bool cleric48_surface(Character *chr);
+ static bool cleric52_dispelMagic(Character *chr);
+ static bool cleric54_removeCondition(Character *chr);
+ static bool cleric55_restoreEnergy(Character *chr);
+ static bool cleric62_raiseDead(Character *chr);
+ static bool cleric63_rejuvinate(Character *chr);
+ static bool cleric64_stoneToFlesh(Character *chr);
+ static bool cleric65_townPortal(Character *chr);
+ static bool cleric73_protectionFromElements(Character *chr);
+ static bool cleric74_resurrection(Character *chr);
+
+ static bool wizard12_detectMagic(Character *chr);
+ static bool wizard15_leatherSkin(Character *chr);
+ static bool wizard16_light(Character *chr) {
+ return cleric15_light(chr);
+ }
+ static bool wizard17_location(Character *chr);
+ static bool wizard24_jump(Character *chr);
+ static bool wizard25_levitate(Character *chr);
+ static bool wizard32_fly(Character *chr);
+ static bool wizard45_guardDog(Character *chr);
+ static bool wizard46_psychicProtection(Character *chr);
+ static bool wizard52_dispelMagic(Character *chr) {
+ return cleric52_dispelMagic(chr);
+ }
+ static bool wizard54_shelter(Character *chr);
+ static bool wizard55_teleport(Character *chr);
+ static bool wizard63_etherialize(Character *chr);
+ static bool wizard64_protectionFromMagic(Character *chr);
+ static bool wizard65_rechargeItem(Character *chr);
+ static bool wizard71_astralSpell(Character *chr);
+ static bool wizard72_duplication(Character *chr);
static SpellFn SPELLS[SPELLS_COUNT];
public:
- static void cast(int spell, Character *chr);
+ /**
+ * Casts a spell
+ * @returns If false, display a 'Done' message.
+ * If true, spell has done it's own UI display
+ */
+ static bool cast(int spell, Character *chr);
};
} // namespace MM1
Commit: 06b6244a4df26e8605f5bf504e6b229a64cbd055
https://github.com/scummvm/scummvm/commit/06b6244a4df26e8605f5bf504e6b229a64cbd055
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: Implementing cleric spells
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/data/spells.h
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index cdb39b3e691..987cd0b16ee 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -161,6 +161,7 @@ void Character::clear() {
_ac = 0;
_food = 0;
_condition = 0;
+ _quest = 0;
_equipped.clear();
_backpack.clear();
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index b096b8c08fd..b89ac6db680 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -202,6 +202,8 @@ struct Character {
int _v66, _v67, _v68, _v69, _v6a, _v6b,
_v6c, _v6e, _v6f;
+ byte _quest = 0;
+
// Non persistent fields
byte _numDrinks = 0;
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index a75ab14cc08..c3165d90f1b 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -20,7 +20,10 @@
*/
#include "mm/mm1/data/spells.h"
+#include "mm/mm1/data/locations.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -124,64 +127,328 @@ Spells::SpellFn Spells::SPELLS[SPELLS_COUNT] = {
placeholder,
};
-bool Spells::cast(int spell, Character *chr) {
+SpellResult Spells::cast(int spell, Character *chr) {
assert(spell < SPELLS_COUNT);
return SPELLS[spell](chr);
}
-bool Spells::cleric14_firstAid(Character *chr) {
- return true;
+SpellResult Spells::cleric14_firstAid(Character *chr) {
+ restoreHp(chr, 8);
+ return SR_SUCCESS_DONE;
}
-bool Spells::cleric15_light(Character *chr) {
- g_globals->_spells._s.light++;
+SpellResult Spells::cleric15_light(Character *chr) {
+ addLight(1);
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult Spells::cleric16_powerCure(Character *chr) {
+ int totalHp = 0;
+ for (uint i = 0; i < g_globals->_currCharacter->_level._current; ++i)
+ totalHp += g_engine->getRandomNumber(10);
+
+ restoreHp(chr, MIN(totalHp, 250));
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric17_protectionFromFear(Character *chr) {
+ g_globals->_spells._s.fear =
+ MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric21_cureWounds(Character *chr) {
+ restoreHp(chr, 16);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric24_protectionFromCold(Character *chr) {
+ g_globals->_spells._s.cold =
+ MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric25_protectionFromIce(Character *chr) {
+ g_globals->_spells._s.fire =
+ MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric26_protectionFromPoison(Character *chr) {
+ g_globals->_spells._s.poison =
+ MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric31_createFood(Character *chr) {
+ if (chr->_food == MAX_FOOD) {
+ return SR_FAILED;
+ } else {
+ chr->_food = MIN(chr->_food + 6, MAX_FOOD);
+ return SR_SUCCESS_DONE;
+ }
+}
+
+SpellResult Spells::cleric32_cureBlindness(Character *chr) {
+ if (chr->_condition & BAD_CONDITION) {
+ return SR_FAILED;
+ } else {
+ chr->_condition &= ~BLINDED;
+ return SR_SUCCESS_DONE;
+ }
+}
+
+SpellResult Spells::cleric33_cureParalysis(Character *chr) {
+ if (chr->_condition & BAD_CONDITION) {
+ return SR_FAILED;
+ } else {
+ chr->_condition &= ~PARALYZED;
+ return SR_SUCCESS_DONE;
+ }
+}
+
+SpellResult Spells::cleric34_lastingLight(Character *chr) {
+ addLight(19);
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult Spells::cleric37_removeQuest(Character *chr) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._quest = 0;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric38_walkOnWater(Character *chr) {
+ g_globals->_spells._s.walk_on_water = MIN(
+ (int)g_globals->_spells._s.walk_on_water + 1, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric41_cureDisease(Character *chr) {
+ if (chr->_condition & BAD_CONDITION) {
+ return SR_FAILED;
+ } else {
+ chr->_condition &= ~DISEASED;
+ return SR_SUCCESS_DONE;
+ }
+}
+
+SpellResult Spells::cleric42_neutralizePoison(Character *chr) {
+ if (chr->_condition & BAD_CONDITION) {
+ return SR_FAILED;
+ } else {
+ chr->_condition &= ~POISONED;
+ return SR_SUCCESS_DONE;
+ }
+}
+
+SpellResult Spells::cleric43_protectionFromAcid(Character *chr) {
+ g_globals->_spells._s.acid =
+ MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric44_protectionFromElectricity(Character *chr) {
+ g_globals->_spells._s.electricity =
+ MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric45_restoreAlignment(Character *chr) {
+ chr->_alignment = chr->_alignmentInitial;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric48_surface(Character *chr) {
+ Maps::Maps &maps = *g_maps;
+ Maps::Map &map = *maps._currentMap;
+ if (map[46] & 4) {
+ return SR_FAILED;
+ } else {
+ maps._mapPos = Common::Point(map[42], map[43]);
+ maps.changeMap(map[11] & (map[12] << 8), map[13]);
+ return SR_SUCCESS_SILENT;
+ }
+}
+
+SpellResult Spells::cleric52_dispelMagic(Character *chr) {
+ Maps::Map &map = *g_maps->_currentMap;
+ if (g_engine->getRandomNumber(100) >= map[38]) {
+ Common::fill(&g_globals->_spells._arr[0],
+ &g_globals->_spells._arr[18], 0);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c.updateAttributes();
+ c.updateAC();
+ if (!(c._condition & BAD_CONDITION))
+ c._condition &= ~(BLINDED | SILENCED);
+ }
+
+ return SR_SUCCESS_DONE;
+ } else {
+ return SR_FAILED;
+ }
+}
+
+SpellResult Spells::cleric54_removeCondition(Character *chr) {
+ if (chr->_condition & BAD_CONDITION) {
+ return SR_FAILED;
+ } else {
+ chr->_condition = FINE;
+
+ if (!chr->_hpBase)
+ chr->_hpBase = 1;
+ restoreHp(chr, 1);
+
+ return SR_SUCCESS_DONE;
+ }
+}
+
+SpellResult Spells::cleric55_restoreEnergy(Character *chr) {
+ if (chr->_level._current < chr->_level._base) {
+ chr->_level._current = MIN(
+ chr->_level._current + g_engine->getRandomNumber(1, 5),
+ (int)chr->_level._base
+ );
+ return SR_SUCCESS_DONE;
+ } else {
+ return SR_FAILED;
+ }
+}
+
+SpellResult Spells::cleric62_raiseDead(Character *chr) {
+ if ((chr->_condition == ERADICATED) ||
+ (chr->_condition & (BAD_CONDITION | DEAD)) ==
+ (BAD_CONDITION | DEAD))
+ return SR_FAILED;
+ int rnd = g_engine->getRandomNumber(100);
+ if (rnd == 100) {
+ // This is such a minute chance, why even have it?
+ Sound::sound(SOUND_3);
+ return SR_FAILED;
+ } else if (rnd > 90) {
+ return SR_FAILED;
+ }
+
+ if (chr->_condition == (BAD_CONDITION | DEAD | STONE))
+ chr->_condition = BAD_CONDITION | STONE;
+ else
+ chr->_condition = FINE;
+
+ chr->_hpBase = 1;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric63_rejuvinate(Character *chr) {
+ if (g_engine->getRandomNumber(100) < 75) {
+ chr->_age._base = MIN(chr->_age._base - g_engine->getRandomNumber(1, 10),
+ 200);
+ return SR_FAILED;
+ } else {
+ // Failed, increase the user's age
+ chr->_age._base = MIN(chr->_age._base + 10, 200);
+ return SR_FAILED;
+ }
+}
+
+SpellResult Spells::cleric64_stoneToFlesh(Character *chr) {
+ if ((chr->_condition == ERADICATED) ||
+ (chr->_condition & (BAD_CONDITION | DEAD)) ==
+ (BAD_CONDITION | DEAD))
+ return SR_FAILED;
+
+ if (chr->_condition == (BAD_CONDITION | DEAD | STONE))
+ chr->_condition = BAD_CONDITION | DEAD;
+ else
+ chr->_condition = FINE;
+
+ chr->_hpBase = 1;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric65_townPortal(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::cleric73_protectionFromElements(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::cleric74_resurrection(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard12_detectMagic(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard15_leatherSkin(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard17_location(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard24_jump(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard25_levitate(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard32_fly(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard45_guardDog(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard46_psychicProtection(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard54_shelter(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard55_teleport(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard63_etherialize(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard64_protectionFromMagic(Character *chr) {
+ g_globals->_spells._s.magic =
+ MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::wizard65_rechargeItem(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard71_astralSpell(Character *chr) {
+ return SR_FAILED;
+}
+
+SpellResult Spells::wizard72_duplication(Character *chr) {
+ return SR_FAILED;
+}
+
+void Spells::restoreHp(Character *chr, uint16 hp) {
+ chr->_hpBase = MIN((int)(chr->_hpBase + hp), (int)chr->_hpMax);
+}
+
+void Spells::addLight(int amount) {
+ g_globals->_spells._s.light = MIN((int)g_globals->_spells._s.light + amount, 255);
g_events->send("Game", GameMessage("UPDATE"));
- return true;
-}
-
-bool Spells::cleric16_powerCure(Character *chr) { return false; }
-bool Spells::cleric17_protectionFromFear(Character *chr) { return false; }
-bool Spells::cleric21_cureWounds(Character *chr) { return false; }
-bool Spells::cleric24_protectionFromCold(Character *chr) { return false; }
-bool Spells::cleric25_protectionFromIce(Character *chr) { return false; }
-bool Spells::cleric26_protectionFromPoison(Character *chr) { return false; }
-bool Spells::cleric31_createFood(Character *chr) { return false; }
-bool Spells::cleric32_cureBlindness(Character *chr) { return false; }
-bool Spells::cleric33_cureParalysis(Character *chr) { return false; }
-bool Spells::cleric34_lastingLight(Character *chr) { return false; }
-bool Spells::cleric37_removeQuest(Character *chr) { return false; }
-bool Spells::cleric38_walkOnWater(Character *chr) { return false; }
-bool Spells::cleric41_cureDisease(Character *chr) { return false; }
-bool Spells::cleric42_neutralizePoison(Character *chr) { return false; }
-bool Spells::cleric43_protectionFromAcid(Character *chr) { return false; }
-bool Spells::cleric44_protectionFromElectricity(Character *chr) { return false; }
-bool Spells::cleric45_restoreAlignment(Character *chr) { return false; }
-bool Spells::cleric48_surface(Character *chr) { return false; }
-bool Spells::cleric52_dispelMagic(Character *chr) { return false; }
-bool Spells::cleric54_removeCondition(Character *chr) { return false; }
-bool Spells::cleric55_restoreEnergy(Character *chr) { return false; }
-bool Spells::cleric62_raiseDead(Character *chr) { return false; }
-bool Spells::cleric63_rejuvinate(Character *chr) { return false; }
-bool Spells::cleric64_stoneToFlesh(Character *chr) { return false; }
-bool Spells::cleric65_townPortal(Character *chr) { return false; }
-bool Spells::cleric73_protectionFromElements(Character *chr) { return false; }
-bool Spells::cleric74_resurrection(Character *chr) { return false; }
-
-bool Spells::wizard12_detectMagic(Character *chr) { return false; }
-bool Spells::wizard15_leatherSkin(Character *chr) { return false; }
-bool Spells::wizard17_location(Character *chr) { return false; }
-bool Spells::wizard24_jump(Character *chr) { return false; }
-bool Spells::wizard25_levitate(Character *chr) { return false; }
-bool Spells::wizard32_fly(Character *chr) { return false; }
-bool Spells::wizard45_guardDog(Character *chr) { return false; }
-bool Spells::wizard46_psychicProtection(Character *chr) { return false; }
-bool Spells::wizard54_shelter(Character *chr) { return false; }
-bool Spells::wizard55_teleport(Character *chr) { return false; }
-bool Spells::wizard63_etherialize(Character *chr) { return false; }
-bool Spells::wizard64_protectionFromMagic(Character *chr) { return false; }
-bool Spells::wizard65_rechargeItem(Character *chr) { return false; }
-bool Spells::wizard71_astralSpell(Character *chr) { return false; }
-bool Spells::wizard72_duplication(Character *chr) { return false; }
+}
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
index 19dc1a6a2af..7cdb831ed56 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/data/spells.h
@@ -30,13 +30,17 @@ namespace MM1 {
#define SPELLS_COUNT (47 * 2)
#define ACTIVE_SPELLS_COUNT 18
+enum SpellResult {
+ SR_SUCCESS_DONE, SR_SUCCESS_SILENT, SR_FAILED
+};
+
struct ActiveSpellsStruct {
byte fear;
byte cold;
byte fire;
byte poison;
byte acid;
- byte elec;
+ byte electricity;
byte magic;
byte light;
byte leather_skin;
@@ -57,60 +61,70 @@ union ActiveSpells {
};
class Spells {
- typedef bool (*SpellFn)(Character *chr);
+ typedef SpellResult (*SpellFn)(Character *chr);
+private:
+ /**
+ * Restores an amount of Hp
+ */
+ static void restoreHp(Character *chr, uint16 hp);
+
+ /**
+ * Increases light duration
+ */
+ static void addLight(int amount);
private:
- static bool placeholder(Character *chr) { return false; }
- static bool cleric14_firstAid(Character *chr);
- static bool cleric15_light(Character *chr);
- static bool cleric16_powerCure(Character *chr);
- static bool cleric17_protectionFromFear(Character *chr);
- static bool cleric21_cureWounds(Character *chr);
- static bool cleric24_protectionFromCold(Character *chr);
- static bool cleric25_protectionFromIce(Character *chr);
- static bool cleric26_protectionFromPoison(Character *chr);
- static bool cleric31_createFood(Character *chr);
- static bool cleric32_cureBlindness(Character *chr);
- static bool cleric33_cureParalysis(Character *chr);
- static bool cleric34_lastingLight(Character *chr);
- static bool cleric37_removeQuest(Character *chr);
- static bool cleric38_walkOnWater(Character *chr);
- static bool cleric41_cureDisease(Character *chr);
- static bool cleric42_neutralizePoison(Character *chr);
- static bool cleric43_protectionFromAcid(Character *chr);
- static bool cleric44_protectionFromElectricity(Character *chr);
- static bool cleric45_restoreAlignment(Character *chr);
- static bool cleric48_surface(Character *chr);
- static bool cleric52_dispelMagic(Character *chr);
- static bool cleric54_removeCondition(Character *chr);
- static bool cleric55_restoreEnergy(Character *chr);
- static bool cleric62_raiseDead(Character *chr);
- static bool cleric63_rejuvinate(Character *chr);
- static bool cleric64_stoneToFlesh(Character *chr);
- static bool cleric65_townPortal(Character *chr);
- static bool cleric73_protectionFromElements(Character *chr);
- static bool cleric74_resurrection(Character *chr);
+ static SpellResult placeholder(Character *chr) { return SR_FAILED; }
+ static SpellResult cleric14_firstAid(Character *chr);
+ static SpellResult cleric15_light(Character *chr);
+ static SpellResult cleric16_powerCure(Character *chr);
+ static SpellResult cleric17_protectionFromFear(Character *chr);
+ static SpellResult cleric21_cureWounds(Character *chr);
+ static SpellResult cleric24_protectionFromCold(Character *chr);
+ static SpellResult cleric25_protectionFromIce(Character *chr);
+ static SpellResult cleric26_protectionFromPoison(Character *chr);
+ static SpellResult cleric31_createFood(Character *chr);
+ static SpellResult cleric32_cureBlindness(Character *chr);
+ static SpellResult cleric33_cureParalysis(Character *chr);
+ static SpellResult cleric34_lastingLight(Character *chr);
+ static SpellResult cleric37_removeQuest(Character *chr);
+ static SpellResult cleric38_walkOnWater(Character *chr);
+ static SpellResult cleric41_cureDisease(Character *chr);
+ static SpellResult cleric42_neutralizePoison(Character *chr);
+ static SpellResult cleric43_protectionFromAcid(Character *chr);
+ static SpellResult cleric44_protectionFromElectricity(Character *chr);
+ static SpellResult cleric45_restoreAlignment(Character *chr);
+ static SpellResult cleric48_surface(Character *chr);
+ static SpellResult cleric52_dispelMagic(Character *chr);
+ static SpellResult cleric54_removeCondition(Character *chr);
+ static SpellResult cleric55_restoreEnergy(Character *chr);
+ static SpellResult cleric62_raiseDead(Character *chr);
+ static SpellResult cleric63_rejuvinate(Character *chr);
+ static SpellResult cleric64_stoneToFlesh(Character *chr);
+ static SpellResult cleric65_townPortal(Character *chr);
+ static SpellResult cleric73_protectionFromElements(Character *chr);
+ static SpellResult cleric74_resurrection(Character *chr);
- static bool wizard12_detectMagic(Character *chr);
- static bool wizard15_leatherSkin(Character *chr);
- static bool wizard16_light(Character *chr) {
+ static SpellResult wizard12_detectMagic(Character *chr);
+ static SpellResult wizard15_leatherSkin(Character *chr);
+ static SpellResult wizard16_light(Character *chr) {
return cleric15_light(chr);
}
- static bool wizard17_location(Character *chr);
- static bool wizard24_jump(Character *chr);
- static bool wizard25_levitate(Character *chr);
- static bool wizard32_fly(Character *chr);
- static bool wizard45_guardDog(Character *chr);
- static bool wizard46_psychicProtection(Character *chr);
- static bool wizard52_dispelMagic(Character *chr) {
+ static SpellResult wizard17_location(Character *chr);
+ static SpellResult wizard24_jump(Character *chr);
+ static SpellResult wizard25_levitate(Character *chr);
+ static SpellResult wizard32_fly(Character *chr);
+ static SpellResult wizard45_guardDog(Character *chr);
+ static SpellResult wizard46_psychicProtection(Character *chr);
+ static SpellResult wizard52_dispelMagic(Character *chr) {
return cleric52_dispelMagic(chr);
}
- static bool wizard54_shelter(Character *chr);
- static bool wizard55_teleport(Character *chr);
- static bool wizard63_etherialize(Character *chr);
- static bool wizard64_protectionFromMagic(Character *chr);
- static bool wizard65_rechargeItem(Character *chr);
- static bool wizard71_astralSpell(Character *chr);
- static bool wizard72_duplication(Character *chr);
+ static SpellResult wizard54_shelter(Character *chr);
+ static SpellResult wizard55_teleport(Character *chr);
+ static SpellResult wizard63_etherialize(Character *chr);
+ static SpellResult wizard64_protectionFromMagic(Character *chr);
+ static SpellResult wizard65_rechargeItem(Character *chr);
+ static SpellResult wizard71_astralSpell(Character *chr);
+ static SpellResult wizard72_duplication(Character *chr);
static SpellFn SPELLS[SPELLS_COUNT];
public:
@@ -119,7 +133,7 @@ public:
* @returns If false, display a 'Done' message.
* If true, spell has done it's own UI display
*/
- static bool cast(int spell, Character *chr);
+ static SpellResult cast(int spell, Character *chr);
};
} // namespace MM1
Commit: 453fab4fe69c642585908e7f59c2d2ca6d809641
https://github.com/scummvm/scummvm/commit/453fab4fe69c642585908e7f59c2d2ca6d809641
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: Display for spell failed
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/views/cast_spell.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 5933aed5f1f..0a6bbc22dfa 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -250,13 +250,7 @@
not_enough_gold: "*** NOT ENOUGH GOLD ***"
not_enough_gems: "*** NOT ENOUGH GEMS ***"
not_enough_sp: "*** NOT ENOUGH SPELL POINTS ***"
- combat_only: "*** COMBAT ONLY ***"
- magic_doesnt_work: "*** MAGIC DOESN'T WORK HERE ***"
- outdoors_only: "*** OUTDOOR ONLY ***"
full: "*** BACKPACK FULL ***"
- done: "*** DONE ***"
- enter_to_cast: "'ENTER' TO CAST"
- cast_on: "CAST ON: '1'-'%d'?"
enhdialogs:
character:
stats:
@@ -638,6 +632,27 @@ stats:
253: "KEY CARD"
254: "EYE OF GORDOS"
255: "(USELESS ITEM)"
+movement:
+ obstructed:
+ 0: " SOLID! "
+ 1: " LOCKED! "
+ 2: " TOO DENSE! "
+ 3: " IMPASSABLE "
+ 4: " ROUGH SEAS "
+ 5: " TOO WINDY! "
+ cant_swim: " CAN'T SWIM"
+ barrier: " BARRIER! "
+view:
+ darkness: " DARKNESS"
+spells:
+ combat_only: "*** COMBAT ONLY ***"
+ magic_doesnt_work: "*** MAGIC DOESN'T WORK HERE ***"
+ outdoors_only: "*** OUTDOOR ONLY ***"
+ failed: "*** SPELL FAILED ***"
+ done: "*** DONE ***"
+ enter_to_cast: "'ENTER' TO CAST"
+ cast_on: "CAST ON: '1'-'%d'?"
+ which_town: "WHICH TOWN (1-5)?"
maps:
map00:
sign: "A SIGN ABOVE THE DOOR READS: "
@@ -662,15 +677,3 @@ maps:
trapdoor: "TRAP DOOR!"
levitate: ", LEVITATION SAVES YOU!"
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
-movement:
- obstructed:
- 0: " SOLID! "
- 1: " LOCKED! "
- 2: " TOO DENSE! "
- 3: " IMPASSABLE "
- 4: " ROUGH SEAS "
- 5: " TOO WINDY! "
- cant_swim: " CAN'T SWIM"
- barrier: " BARRIER! "
-view:
- darkness: " DARKNESS"
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index c3165d90f1b..fe382fc8f9f 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -368,6 +368,8 @@ SpellResult Spells::cleric64_stoneToFlesh(Character *chr) {
}
SpellResult Spells::cleric65_townPortal(Character *chr) {
+
+
return SR_FAILED;
}
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index e398eeae091..e73423070c2 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -126,15 +126,15 @@ bool SpellCasting::isMagicAllowed() const {
Common::String SpellCasting::getSpellError() const {
switch (_spellState) {
case SS_NOT_ENOUGH_SP:
- return STRING["dialogs.misc.not_enough_sp"];
+ return STRING["spells.not_enough_sp"];
case SS_NOT_ENOUGH_GEMS:
- return STRING["dialogs.misc.not_enough_gems"];
+ return STRING["spells.not_enough_gems"];
case SS_COMBAT_ONLY:
- return STRING["dialogs.misc.combat_only"];
+ return STRING["spells.combat_only"];
case SS_OUTDOORS_ONLY:
- return STRING["dialogs.misc.outdoors_only"];
+ return STRING["spells.outdoors_only"];
default:
- return STRING["dialogs.misc.done"];
+ return STRING["spells.done"];
}
}
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/cast_spell.cpp
index 1e63e7bd6f8..7264a497f93 100644
--- a/engines/mm/mm1/views/cast_spell.cpp
+++ b/engines/mm/mm1/views/cast_spell.cpp
@@ -108,7 +108,7 @@ void CastSpell::draw() {
case SELECT_CHAR:
writeString(22, 3, Common::String::format(
- STRING["dialogs.misc.cast_on"].c_str(),
+ STRING["spells.cast_on"].c_str(),
(int)g_globals->_party.size()
));
break;
@@ -193,15 +193,30 @@ void CastSpell::performSpell(Character *chr) {
spellDone(STRING["dialogs.misc.magic_doesnt_work"], 5);
} else {
// Cast the spell
- Spells::cast(_spellIndex, chr);
-
- // Display spell done
- clearSurface();
- writeString(14, 2, STRING["dialogs.misc.done"]);
- Sound::sound(SOUND_2);
-
- g_globals->_party.updateAC();
- delaySeconds(3);
+ switch (Spells::cast(_spellIndex, chr)) {
+ case SR_FAILED:
+ // Spell failed
+ clearSurface();
+ writeString(10, 2, STRING["spells.failed"]);
+
+ Sound::sound(SOUND_2);
+ delaySeconds(3);
+ break;
+
+ case SR_SUCCESS_DONE:
+ // Display spell done
+ clearSurface();
+ writeString(14, 2, STRING["dialogs.misc.done"]);
+ g_globals->_party.updateAC();
+
+ Sound::sound(SOUND_2);
+ delaySeconds(3);
+ break;
+
+ default:
+ // Spell done, but don't display done message
+ break;
+ }
}
}
Commit: 975b85cfef86ab729a8f207bedaabd9bff993347
https://github.com/scummvm/scummvm/commit/975b85cfef86ab729a8f207bedaabd9bff993347
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: Remaining cleric spells
Changed paths:
engines/mm/mm1/data/locations.h
engines/mm/mm1/data/spells.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/locations.h b/engines/mm/mm1/data/locations.h
index 9e2890775c3..b00fc7f54e8 100644
--- a/engines/mm/mm1/data/locations.h
+++ b/engines/mm/mm1/data/locations.h
@@ -93,6 +93,13 @@ struct TrainingData {
};
};
+struct TownData {
+ static const byte TOWN_MAP_ID1[5];
+ static const byte TOWN_MAP_ID2[5];
+ static const byte TOWN_MAP_X[5];
+ static const byte TOWN_MAP_Y[5];
+};
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index fe382fc8f9f..fa54e5baf3c 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -368,17 +368,66 @@ SpellResult Spells::cleric64_stoneToFlesh(Character *chr) {
}
SpellResult Spells::cleric65_townPortal(Character *chr) {
+ Sound::sound(SOUND_2);
+ InfoMessage msg(
+ STRING["spells.which_town"],
+ [](const Common::KeyState &keyState) {
+ switch (keyState.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ g_events->focusedView()->close();
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5: {
+ Maps::Maps &maps = *g_maps;
+ int townIndex = keyState.keycode - Common::KEYCODE_1;
+
+ maps._mapPos.x = TownData::TOWN_MAP_X[townIndex];
+ maps._mapPos.y = TownData::TOWN_MAP_Y[townIndex];
+ maps.changeMap(
+ TownData::TOWN_MAP_ID1[townIndex] |
+ (TownData::TOWN_MAP_ID1[townIndex] << 8),
+ 1);
+
+ g_events->close();
+ return;
+ }
+
+ default:
+ break;
+ }
+ }
+ );
-
- return SR_FAILED;
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::cleric73_protectionFromElements(Character *chr) {
- return SR_FAILED;
+ int amount = g_globals->_currCharacter->_level._current + 25;
+
+ for (int i = 0; i < 6; ++i)
+ g_globals->_spells._arr[i] = amount;
+
+ return SR_SUCCESS_DONE;
}
SpellResult Spells::cleric74_resurrection(Character *chr) {
- return SR_FAILED;
+ if (chr->_condition == ERADICATED)
+ return SR_FAILED;
+
+ if (chr->_age._base < 10 || chr->_age._base > 200)
+ chr->_age._base = 200;
+
+ if (g_engine->getRandomNumber(100) > 75)
+ return SR_FAILED;
+
+ chr->_endurance._base = MAX((int)chr->_endurance._base - 1, 1);
+ chr->_condition = FINE;
+ restoreHp(chr, 1);
+
+ return SR_SUCCESS_DONE;
}
SpellResult Spells::wizard12_detectMagic(Character *chr) {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 1764f49aa96..b50577eaedc 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS := \
mm1/data/character.o \
mm1/data/game_state.o \
mm1/data/items.o \
+ mm1/data/locations.o \
mm1/data/party.o \
mm1/data/roster.o \
mm1/data/spells.o \
Commit: 4f61bb82ddb2c1d9240f2a2f85fbe89d9ba8fc86
https://github.com/scummvm/scummvm/commit/4f61bb82ddb2c1d9240f2a2f85fbe89d9ba8fc86
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: Starting wizard spells
Changed paths:
A engines/mm/mm1/data/locations.cpp
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/data/locations.cpp b/engines/mm/mm1/data/locations.cpp
new file mode 100644
index 00000000000..422e7257019
--- /dev/null
+++ b/engines/mm/mm1/data/locations.cpp
@@ -0,0 +1,33 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/locations.h"
+
+namespace MM {
+namespace MM1 {
+
+const byte TownData::TOWN_MAP_ID1[5] = { 4, 3, 3, 2, 0x1A };
+const byte TownData::TOWN_MAP_ID2[5] = { 6, 0xC, 2, 8, 0xB };
+const byte TownData::TOWN_MAP_X[5] = { 8, 1, 11, 12, 4 };
+const byte TownData::TOWN_MAP_Y[5] = { 5, 12, 13, 8, 6 };
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index fa54e5baf3c..afc21055197 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -431,11 +431,13 @@ SpellResult Spells::cleric74_resurrection(Character *chr) {
}
SpellResult Spells::wizard12_detectMagic(Character *chr) {
+ error("TODO: detectMagic");
return SR_FAILED;
}
SpellResult Spells::wizard15_leatherSkin(Character *chr) {
- return SR_FAILED;
+ g_globals->_spells._s.leather_skin = g_globals->_currCharacter->_level._current;
+ return SR_SUCCESS_DONE;
}
SpellResult Spells::wizard17_location(Character *chr) {
@@ -443,7 +445,36 @@ SpellResult Spells::wizard17_location(Character *chr) {
}
SpellResult Spells::wizard24_jump(Character *chr) {
- return SR_FAILED;
+ Maps::Maps &maps = *g_maps;
+ Maps::Map &map = *maps._currentMap;
+
+ if ((maps._currentWalls & maps._forwardMask) != 0)
+ return SR_FAILED;
+ if ((map._states[maps._mapOffset] & maps._forwardMask & 0x55) != 0)
+ return SR_FAILED;
+ if ((map._walls[maps._mapOffset + maps._forwardOffset] &
+ maps._forwardMask) != 0)
+ return SR_FAILED;
+ if ((map._states[maps._mapOffset + maps._forwardOffset]
+ & maps._forwardMask & 0x55) != 0)
+ return SR_FAILED;
+
+ // The delta will be two steps in the facing direction.
+ // Ensure that that doesn't end up outside the map bounds
+ Common::Point delta = maps.getMoveDelta(maps._forwardMask);
+ delta.x *= 2;
+ delta.y *= 2;
+
+ Common::Point newPos = maps._mapPos + delta;
+ if (newPos.x < 0 || newPos.y < 0 ||
+ newPos.x >= MAP_W || newPos.y >= MAP_H)
+ return SR_FAILED;
+
+ // Move the two steps
+ g_maps->step(delta);
+ g_events->send("Game", GameMessage("UPDATE"));
+
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard25_levitate(Character *chr) {
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index d57c8a5e97b..594d3c10165 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -146,7 +146,7 @@ void ViewBase::forward(KeybindingAction action) {
}
// Get the delta X/Y from the direction
- Common::Point delta = getMoveDelta(mask);
+ Common::Point delta = g_maps->getMoveDelta(mask);
// Check for obstructions
if (!g_globals->_intangible) {
@@ -194,7 +194,7 @@ void ViewBase::forward(KeybindingAction action) {
void ViewBase::backwards() {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *g_globals->_maps._currentMap;
- Common::Point delta = getMoveDelta(maps._backwardsMask);
+ Common::Point delta = g_maps->getMoveDelta(maps._backwardsMask);
if (!g_globals->_intangible) {
if (maps._currentWalls & maps._backwardsMask) {
@@ -219,19 +219,6 @@ void ViewBase::backwards() {
update();
}
-Common::Point ViewBase::getMoveDelta(byte mask) const {
- switch (mask) {
- case Maps::DIRMASK_E:
- return Common::Point(1, 0);
- case Maps::DIRMASK_W:
- return Common::Point(-1, 0);
- case Maps::DIRMASK_S:
- return Common::Point(0, -1);
- default:
- return Common::Point(0, 1);
- }
-}
-
void ViewBase::obstructed(byte mask) {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 18e48ce95b0..dca05ef0e19 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -62,11 +62,6 @@ private:
*/
void backwards();
- /**
- * Gets the moveement delta given a direction mask
- */
- Common::Point getMoveDelta(byte mask) const;
-
/**
* Forward movement is obstructed
*/
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 91bec804bc4..f9725dc57b3 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -444,6 +444,19 @@ void Maps::clearSpecial() {
_currentMap->_states[_mapOffset] &= ~CELL_SPECIAL;
}
+Common::Point Maps::getMoveDelta(byte mask) {
+ switch (mask) {
+ case DIRMASK_E:
+ return Common::Point(1, 0);
+ case DIRMASK_W:
+ return Common::Point(-1, 0);
+ case DIRMASK_S:
+ return Common::Point(0, -1);
+ default:
+ return Common::Point(0, 1);
+ }
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index bf8499f39d1..ec11d13390d 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -162,6 +162,11 @@ public:
* that trigger combat after the first time
*/
void clearSpecial();
+
+ /**
+ * Gets the moveement delta given a direction mask
+ */
+ static Common::Point getMoveDelta(byte mask);
};
} // namespace Maps
Commit: bd2d8bc67ebfff09e383c38b3266c58ebd8081d5
https://github.com/scummvm/scummvm/commit/bd2d8bc67ebfff09e383c38b3266c58ebd8081d5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: Implement wizard levitate spell
Changed paths:
engines/mm/mm1/data/spells.cpp
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index afc21055197..3ba3078e391 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -478,7 +478,9 @@ SpellResult Spells::wizard24_jump(Character *chr) {
}
SpellResult Spells::wizard25_levitate(Character *chr) {
- return SR_FAILED;
+ g_globals->_spells._s.levitate =
+ g_globals->_currCharacter->_level._current;
+ return SR_SUCCESS_DONE;
}
SpellResult Spells::wizard32_fly(Character *chr) {
Commit: b27f00dc5347d0fb10e90ec6e5283ccbe6be73dd
https://github.com/scummvm/scummvm/commit/b27f00dc5347d0fb10e90ec6e5283ccbe6be73dd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: In progress implementing Fly spell destination selection
Changed paths:
A engines/mm/mm1/views/spells/fly.cpp
A engines/mm/mm1/views/spells/fly.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/data/spells.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 0a6bbc22dfa..f42a114f7c1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -251,6 +251,9 @@
not_enough_gems: "*** NOT ENOUGH GEMS ***"
not_enough_sp: "*** NOT ENOUGH SPELL POINTS ***"
full: "*** BACKPACK FULL ***"
+ spells:
+ fly_to_x: "FLY TO (A-E): "
+ fly_to_y: "(1-4): "
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 3ba3078e391..c616434186d 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -24,6 +24,7 @@
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
+#include "mm/mm1/views/spells/fly.h"
namespace MM {
namespace MM1 {
@@ -127,6 +128,34 @@ Spells::SpellFn Spells::SPELLS[SPELLS_COUNT] = {
placeholder,
};
+byte FLY_MAP_ID1[20] = {
+ 1, 0, 4, 5, 0x12,
+ 2, 3, 0x11, 5, 6,
+ 2, 1, 4, 6, 0x1A,
+ 3, 3, 4, 1, 0x1B
+};
+
+byte FLY_MAP_ID2[20] = {
+ 0xF, 0xA, 3, 5, 1,
+ 5, 7, 0xA, 0xB, 7,
+ 0xB, 1, 9, 1, 0xB,
+ 1, 0xD, 0xF, 8, 1
+};
+
+byte FLY_MAP_X[20] = {
+ 15, 8, 11, 0, 9,
+ 15, 3, 10, 4, 11,
+ 15, 3, 3, 7, 12,
+ 14, 11, 5, 7, 15
+};
+
+byte FLY_MAP_Y[20] = {
+ 7, 10, 0, 8, 11,
+ 7, 2, 10, 0, 0,
+ 15, 3, 9, 0, 6,
+ 14, 15, 15, 7, 15
+};
+
SpellResult Spells::cast(int spell, Character *chr) {
assert(spell < SPELLS_COUNT);
return SPELLS[spell](chr);
@@ -484,7 +513,13 @@ SpellResult Spells::wizard25_levitate(Character *chr) {
}
SpellResult Spells::wizard32_fly(Character *chr) {
- return SR_FAILED;
+ Views::Spells::Fly::show(
+ [](int mapId) {
+ error("TODO: fly to map %d", mapId);
+ }
+ );
+
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard45_guardDog(Character *chr) {
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
index 7cdb831ed56..c844cd06c4b 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/data/spells.h
@@ -34,6 +34,12 @@ enum SpellResult {
SR_SUCCESS_DONE, SR_SUCCESS_SILENT, SR_FAILED
};
+extern byte FLY_MAP_ID1[20];
+extern byte FLY_MAP_ID2[20];
+extern byte FLY_MAP_X[20];
+extern byte FLY_MAP_Y[20];
+
+
struct ActiveSpellsStruct {
byte fear;
byte cold;
diff --git a/engines/mm/mm1/views/spells/fly.cpp b/engines/mm/mm1/views/spells/fly.cpp
new file mode 100644
index 00000000000..4c0fadac511
--- /dev/null
+++ b/engines/mm/mm1/views/spells/fly.cpp
@@ -0,0 +1,102 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/spells/fly.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+void Fly::show(FlyCallback callback) {
+ Fly *fly = dynamic_cast<Fly *>(g_events->findView("Fly"));
+ assert(fly);
+
+ fly->_callback = callback;
+ fly->focus();
+}
+
+Fly::Fly() : TextView("Fly") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Fly::msgFocus(const FocusMessage &) {
+ _mode = SELECT_X;
+ _xIndex = _yIndex = 0;
+ return 0;
+}
+
+void Fly::draw() {
+ clearSurface();
+ escToGoBack(0);
+
+ writeString(9, 0, STRING["dialogs.spells.fly_to_x"]);
+ writeChar((_mode == SELECT_X) ? '_' : 'A' + _xIndex);
+
+ if (_mode == SELECT_Y || _mode == CAST) {
+ writeString(16, 1, STRING["dialogs.spells.fly_to_y"]);
+ writeChar((_mode == SELECT_Y) ? '_' : '1' + _yIndex);
+ }
+
+ if (_mode == CAST) {
+ writeString(24, 3, STRING["spells.enter_to_cast"]);
+ }
+}
+
+bool Fly::msgKeypress(const KeypressMessage &msg) {
+ Maps::Maps &maps = *g_maps;
+
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+
+ } else if (_mode == SELECT_X && msg.keycode >= Common::KEYCODE_a
+ && msg.keycode <= Common::KEYCODE_d) {
+ // X map selected
+ _mode = SELECT_Y;
+ _xIndex = msg.keycode - Common::KEYCODE_a;
+ redraw();
+
+ } else if (_mode == SELECT_Y && msg.keycode >= Common::KEYCODE_1
+ && msg.keycode <= Common::KEYCODE_4) {
+ // Y map selected
+ _mode = CAST;
+ _yIndex = msg.keycode - Common::KEYCODE_1;
+ redraw();
+
+ } else if (_mode == CAST && msg.keycode == Common::KEYCODE_RETURN) {
+ // Spell was cast
+ int mapIndex = _yIndex * 5 + _xIndex;
+ int id = FLY_MAP_ID1[mapIndex] | ((int)FLY_MAP_ID2[mapIndex] << 8);
+
+ maps._mapPos.x = FLY_MAP_X[mapIndex];
+ maps._mapPos.y = FLY_MAP_Y[mapIndex];
+ maps.changeMap(id, 2);
+ close();
+ }
+
+ return true;
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/spells/fly.h b/engines/mm/mm1/views/spells/fly.h
new file mode 100644
index 00000000000..16d1c492937
--- /dev/null
+++ b/engines/mm/mm1/views/spells/fly.h
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SPELLS_FLY_H
+#define MM1_VIEWS_SPELLS_FLY_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+/**
+ * Callback that specifies the map selected,
+ * or -1 if escape was pressed
+ */
+typedef void (*FlyCallback)(int mapId);
+
+class Fly : public TextView {
+private:
+ FlyCallback _callback;
+ enum Mode {
+ SELECT_X, SELECT_Y, CAST
+ };
+ Mode _mode = SELECT_X;
+ int _xIndex = 0, _yIndex = 0;
+
+ /**
+ * Constructor
+ */
+ Fly();
+public:
+ /**
+ * Show the view
+ */
+ static void show(FlyCallback callback);
+public:
+ virtual ~Fly() {
+ }
+
+ /**
+ * Show the view
+ */
+ bool msgFocus(const FocusMessage &) override;
+
+ /**
+ * Draw the view contents
+ */
+ void draw() override;
+
+ /**
+ * Keypress handler
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b50577eaedc..9ce92e5574a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -42,6 +42,7 @@ MODULE_OBJS := \
mm1/views/locations/tavern.o \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
+ mm1/views/spells/fly.o \
mm1/views/are_you_ready.o \
mm1/views/cast_spell.o \
mm1/views/character_base.o \
Commit: 0a99c1ad78d750fb7323cd8cd364b9d430dd9690
https://github.com/scummvm/scummvm/commit/0a99c1ad78d750fb7323cd8cd364b9d430dd9690
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:05+01:00
Commit Message:
MM: MM1: Adding a cast console command
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/game/spell_casting.h
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index e439188db13..3f0cbc09d8c 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -36,6 +36,7 @@ Console::Console() : GUI::Debugger() {
registerCmd("map", WRAP_METHOD(Console, cmdMap));
registerCmd("pos", WRAP_METHOD(Console, cmdPos));
registerCmd("intangible", WRAP_METHOD(Console, cmdIntangible));
+ registerCmd("cast", WRAP_METHOD(Console, cmdCast));
}
bool Console::cmdDumpMap(int argc, const char **argv) {
@@ -203,5 +204,33 @@ bool Console::cmdIntangible(int argc, const char **argv) {
return true;
}
+bool Console::cmdCast(int argc, const char **argv) {
+ if (argc != 3) {
+ debugPrintf("%s <level> <number>\n", argv[0]);
+ return true;
+ } else {
+ Character *c = g_globals->_currCharacter;
+ if (!c || (c->_class != CLERIC && c->_class != SORCERER
+ && c->_class != ARCHER)) {
+ uint i;
+ for (i = 0; i < g_globals->_party.size(); ++i) {
+ if (g_globals->_party[i]._class == SORCERER) {
+ c = &g_globals->_party[i];
+ break;
+ }
+ }
+ if (i == g_globals->_party.size()) {
+ debugPrintf("Could not find sorcerer in party\n");
+ return true;
+ }
+ }
+
+ int spellIndex = getSpellIndex(c, strToInt(argv[1]), strToInt(argv[2]));
+ setSpell(spellIndex, 0, 0);
+ Spells::cast(_spellIndex, c);
+ return false;
+ }
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index b907c02437b..2654f883b46 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -23,11 +23,12 @@
#define MM_MM1_CONSOLE_H
#include "gui/debugger.h"
+#include "mm/mm1/game/spell_casting.h"
namespace MM {
namespace MM1 {
-class Console : public GUI::Debugger {
+class Console : public GUI::Debugger, public MM1::Game::SpellCasting {
protected:
/**
* Used to dump a map's code and data
@@ -54,6 +55,11 @@ protected:
*/
bool cmdPos(int argc, const char **argv);
+ /**
+ * Casts a spell
+ */
+ bool cmdCast(int argc, const char **argv);
+
public:
Console();
~Console() override {}
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index e73423070c2..b816ca59153 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -69,20 +69,26 @@ enum SpellFlag {
SF_OUTDOORS_ONLY = 0x10
};
-void SpellCasting::setSpell(Character *chr, int lvl, int num) {
+int SpellCasting::getSpellIndex(Character *chr, int lvl, int num) {
int lvlNum;
int setNum = chr->_class == ARCHER || chr->_class == SORCERER ? 1 : 0;
- _spellState = SS_OK;
-
- // Figure the offset in the spell list
int spellNum = num - 1;
for (lvlNum = 2; lvlNum < MIN(lvl, 5); ++lvlNum)
spellNum += 8;
for (lvlNum = 5; lvlNum < lvl; ++lvlNum)
spellNum += 5;
- // Get required SP
int spellIndex = setNum * 47 + spellNum;
+ return spellIndex;
+}
+
+void SpellCasting::setSpell(Character *chr, int lvl, int num) {
+ _spellState = SS_OK;
+
+ // Figure the offset in the spell list
+ int spellIndex = getSpellIndex(chr, lvl, num);
+
+ // Get required SP
int requiredSp = lvl - 1;
if (SPELLS_SP_GEMS[spellIndex] < 0)
diff --git a/engines/mm/mm1/game/spell_casting.h b/engines/mm/mm1/game/spell_casting.h
index d27c49929de..5cd7c1d8da7 100644
--- a/engines/mm/mm1/game/spell_casting.h
+++ b/engines/mm/mm1/game/spell_casting.h
@@ -47,6 +47,11 @@ public:
*/
void setSpell(Character *chr, int lvl, int num);
+ /**
+ * Get the index in the spell array for a given spell
+ */
+ static int getSpellIndex(Character *chr, int lvl, int num);
+
/**
* Sets a spell directly by index
*/
Commit: b209a6a1df3d90203213ba2699479b6b98738433
https://github.com/scummvm/scummvm/commit/b209a6a1df3d90203213ba2699479b6b98738433
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Fix mapping spell level/num to spell index
Changed paths:
engines/mm/mm1/game/spell_casting.cpp
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index b816ca59153..4e96460a8ea 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -73,7 +73,7 @@ int SpellCasting::getSpellIndex(Character *chr, int lvl, int num) {
int lvlNum;
int setNum = chr->_class == ARCHER || chr->_class == SORCERER ? 1 : 0;
int spellNum = num - 1;
- for (lvlNum = 2; lvlNum < MIN(lvl, 5); ++lvlNum)
+ for (lvlNum = 2; lvlNum <= MIN(lvl, 5); ++lvlNum)
spellNum += 8;
for (lvlNum = 5; lvlNum < lvl; ++lvlNum)
spellNum += 5;
Commit: ff46e2a56c4dd2a38e2aae7473241853f283f2fc
https://github.com/scummvm/scummvm/commit/ff46e2a56c4dd2a38e2aae7473241853f283f2fc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Fix display of Fly spell selection view
Changed paths:
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/spells/fly.cpp
engines/mm/mm1/views/spells/fly.h
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index c616434186d..5c8098d98da 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -514,8 +514,15 @@ SpellResult Spells::wizard25_levitate(Character *chr) {
SpellResult Spells::wizard32_fly(Character *chr) {
Views::Spells::Fly::show(
- [](int mapId) {
- error("TODO: fly to map %d", mapId);
+ [](int mapIndex) {
+ if (mapIndex != -1) {
+ Maps::Maps &maps = *g_maps;
+ int id = FLY_MAP_ID1[mapIndex] | ((int)FLY_MAP_ID2[mapIndex] << 8);
+
+ maps._mapPos.x = FLY_MAP_X[mapIndex];
+ maps._mapPos.y = FLY_MAP_Y[mapIndex];
+ maps.changeMap(id, 2);
+ }
}
);
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 069c5806b63..4ede3413321 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -43,6 +43,7 @@
#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
+#include "mm/mm1/views/spells/fly.h"
namespace MM {
namespace MM1 {
@@ -70,6 +71,7 @@ private:
Views::Locations::Temple _temple;
Views::Locations::Training _training;
+ Views::Spells::Fly _flySpell;
public:
Dialogs() {}
};
diff --git a/engines/mm/mm1/views/spells/fly.cpp b/engines/mm/mm1/views/spells/fly.cpp
index 4c0fadac511..5e01b40ad68 100644
--- a/engines/mm/mm1/views/spells/fly.cpp
+++ b/engines/mm/mm1/views/spells/fly.cpp
@@ -36,7 +36,7 @@ void Fly::show(FlyCallback callback) {
}
Fly::Fly() : TextView("Fly") {
- _bounds = getLineBounds(20, 24);
+ _bounds = getLineBounds(21, 24);
}
bool Fly::msgFocus(const FocusMessage &) {
@@ -63,10 +63,9 @@ void Fly::draw() {
}
bool Fly::msgKeypress(const KeypressMessage &msg) {
- Maps::Maps &maps = *g_maps;
-
if (msg.keycode == Common::KEYCODE_ESCAPE) {
close();
+ _callback(-1);
} else if (_mode == SELECT_X && msg.keycode >= Common::KEYCODE_a
&& msg.keycode <= Common::KEYCODE_d) {
@@ -84,13 +83,9 @@ bool Fly::msgKeypress(const KeypressMessage &msg) {
} else if (_mode == CAST && msg.keycode == Common::KEYCODE_RETURN) {
// Spell was cast
- int mapIndex = _yIndex * 5 + _xIndex;
- int id = FLY_MAP_ID1[mapIndex] | ((int)FLY_MAP_ID2[mapIndex] << 8);
-
- maps._mapPos.x = FLY_MAP_X[mapIndex];
- maps._mapPos.y = FLY_MAP_Y[mapIndex];
- maps.changeMap(id, 2);
close();
+ int mapIndex = _yIndex * 5 + _xIndex;
+ _callback(mapIndex);
}
return true;
diff --git a/engines/mm/mm1/views/spells/fly.h b/engines/mm/mm1/views/spells/fly.h
index 16d1c492937..c868c4a4732 100644
--- a/engines/mm/mm1/views/spells/fly.h
+++ b/engines/mm/mm1/views/spells/fly.h
@@ -44,18 +44,21 @@ private:
Mode _mode = SELECT_X;
int _xIndex = 0, _yIndex = 0;
- /**
- * Constructor
- */
- Fly();
public:
/**
* Show the view
*/
static void show(FlyCallback callback);
public:
- virtual ~Fly() {
- }
+ /**
+ * Constructor
+ */
+ Fly();
+
+ /**
+ * Destructor
+ */
+ virtual ~Fly() {}
/**
* Show the view
Commit: 85b8b26c3a18ca42433cbc125e88ff6ceadd853f
https://github.com/scummvm/scummvm/commit/85b8b26c3a18ca42433cbc125e88ff6ceadd853f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Implemented some more wizard spells
Changed paths:
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/data/spells.h
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 5c8098d98da..28134b371f1 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -530,11 +530,15 @@ SpellResult Spells::wizard32_fly(Character *chr) {
}
SpellResult Spells::wizard45_guardDog(Character *chr) {
- return SR_FAILED;
+ g_globals->_spells._s.guard_dog =
+ g_globals->_currCharacter->_level._current;
+ return SR_SUCCESS_DONE;
}
SpellResult Spells::wizard46_psychicProtection(Character *chr) {
- return SR_FAILED;
+ g_globals->_spells._s.psychic_protection =
+ g_globals->_currCharacter->_level._current;
+ return SR_SUCCESS_DONE;
}
SpellResult Spells::wizard54_shelter(Character *chr) {
@@ -546,7 +550,11 @@ SpellResult Spells::wizard55_teleport(Character *chr) {
}
SpellResult Spells::wizard63_etherialize(Character *chr) {
- return SR_FAILED;
+ g_events->draw();
+ g_maps->_currentState = 0;
+ g_maps->step(Common::Point(1, 0));
+
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard64_protectionFromMagic(Character *chr) {
@@ -560,7 +568,12 @@ SpellResult Spells::wizard65_rechargeItem(Character *chr) {
}
SpellResult Spells::wizard71_astralSpell(Character *chr) {
- return SR_FAILED;
+ Maps::Maps &maps = *g_maps;
+ maps._mapPos.x = 7;
+ maps._mapPos.y = 0;
+ maps.changeMap(0xb1a, 3);
+
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard72_duplication(Character *chr) {
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
index c844cd06c4b..2ad87d9775c 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/data/spells.h
@@ -53,7 +53,7 @@ struct ActiveSpellsStruct {
byte levitate;
byte walk_on_water;
byte guard_dog;
- byte psychic_protecti;
+ byte psychic_protection;
byte bless;
byte invisbility;
byte shield;
Commit: 183c9055bb93534da69256600a451727369ee960
https://github.com/scummvm/scummvm/commit/183c9055bb93534da69256600a451727369ee960
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Adding rest view
Changed paths:
A engines/mm/mm1/game/encounter.cpp
A engines/mm/mm1/game/encounter.h
A engines/mm/mm1/game/rest.cpp
A engines/mm/mm1/game/rest.h
A engines/mm/mm1/views/rest.cpp
A engines/mm/mm1/views/rest.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
new file mode 100644
index 00000000000..fbf2cac85e7
--- /dev/null
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -0,0 +1,35 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/game/encounter.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+void Encounter::execute() {
+ // TODO: Handle properly
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
new file mode 100644
index 00000000000..c33ebfb397e
--- /dev/null
+++ b/engines/mm/mm1/game/encounter.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_ENCOUNTER_H
+#define MM1_GAME_ENCOUNTER_H
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+struct Encounter {
+ static void execute();
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/game/rest.cpp b/engines/mm/mm1/game/rest.cpp
new file mode 100644
index 00000000000..0798e24a34b
--- /dev/null
+++ b/engines/mm/mm1/game/rest.cpp
@@ -0,0 +1,36 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/sound.h"
+#include "mm/mm1/game/rest.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+void Rest::execute() {
+ // TODO: Handle properly
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/rest.h b/engines/mm/mm1/game/rest.h
new file mode 100644
index 00000000000..d4c322b3206
--- /dev/null
+++ b/engines/mm/mm1/game/rest.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_REST_H
+#define MM1_GAME_REST_H
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+struct Rest {
+ static void execute();
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/rest.cpp b/engines/mm/mm1/views/rest.cpp
new file mode 100644
index 00000000000..74dfa7d0a3a
--- /dev/null
+++ b/engines/mm/mm1/views/rest.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/rest.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/game/rest.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Rest::Rest() : TextView("Rest") {
+ _bounds = getLineBounds(21, 24);
+}
+
+bool Rest::msgGame(const GameMessage &msg) {
+ if (msg._name == "Rest") {
+ // Show the dialog
+ addView(this);
+ return true;
+ }
+
+ return false;
+}
+
+bool Rest::msgFocus(const FocusMessage &msg) {
+ _mode = CONFIRM;
+ if (g_maps->_currentState & 8)
+ tooDangerous();
+}
+
+void Rest::draw() {
+ if (_mode == CONFIRM) {
+ clearSurface();
+ writeString(0, 0, STRING["dialogs.game.rest.rest_here"]);
+ }
+}
+
+bool Rest::msgKeypress(const KeypressMessage &msg) {
+ if (_mode == CONFIRM) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE ||
+ msg.keycode == Common::KEYCODE_n) {
+ close();
+ } else if (msg.keycode == Common::KEYCODE_y) {
+ Game::Rest::execute();
+ restComplete();
+ }
+ }
+
+ return true;
+}
+
+void Rest::tooDangerous() {
+ _mode = RESPONSE;
+ clearSurface();
+ writeString(2, 0, STRING["dialogs.game.rest.too_dangerous"]);
+ delaySeconds(3);
+}
+
+void Rest::restComplete() {
+ _mode = RESPONSE;
+ clearSurface();
+ writeString(0, 0, STRING["dialogs.game.rest.rest_complete"]);
+ delaySeconds(3);
+}
+
+void Rest::timeout() {
+ close();
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/rest.h b/engines/mm/mm1/views/rest.h
new file mode 100644
index 00000000000..a91b22e3491
--- /dev/null
+++ b/engines/mm/mm1/views/rest.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_REST_H
+#define MM1_VIEWS_REST_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Rest : public TextView {
+private:
+ enum Mode { CONFIRM, RESPONSE };
+ Mode _mode = CONFIRM;
+
+ void tooDangerous();
+ void restComplete();
+public:
+ Rest();
+ virtual ~Rest() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgGame(const GameMessage &msg) override;
+ void timeout() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 9ce92e5574a..826bf7dff9d 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -21,6 +21,8 @@ MODULE_OBJS := \
mm1/data/party.o \
mm1/data/roster.o \
mm1/data/spells.o \
+ mm1/game/encounter.o \
+ mm1/game/rest.o \
mm1/game/search.o \
mm1/game/spell_casting.o \
mm1/game/view_base.o \
@@ -60,6 +62,7 @@ MODULE_OBJS := \
mm1/views/order.o \
mm1/views/protect.o \
mm1/views/quick_ref.o \
+ mm1/views/rest.o \
mm1/views/statue.o \
mm1/views/title.o \
mm1/views/text_entry.o \
Commit: 662e6916c252763a43160bc42d9cef9b03289f3d
https://github.com/scummvm/scummvm/commit/662e6916c252763a43160bc42d9cef9b03289f3d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Further rest implementation, added updateSP
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/game/rest.cpp
engines/mm/mm1/game/rest.h
engines/mm/mm1/views/cast_spell.cpp
engines/mm/mm1/views/character_base.cpp
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/rest.cpp
engines/mm/mm1/views/rest.h
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 987cd0b16ee..3a14123c11b 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -113,7 +113,7 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_v2c);
s.syncAsByte(_sp._base);
s.syncAsByte(_v2e);
- _slvl.synchronize(s);
+ _spellLevel.synchronize(s);
s.syncAsUint16LE(_gems);
s.syncAsUint16LE(_hpBase);
@@ -154,7 +154,7 @@ void Character::clear() {
_age = 0;
_exp = 0;
_sp = 0;
- _slvl = 0;
+ _spellLevel = 0;
_gems = 0;
_hpBase = _hp = _hpMax = 0;
_gold = 0;
@@ -308,7 +308,7 @@ void Character::updateAttributes() {
_accuracy.reset();
_luck.reset();
_level.reset();
- _slvl.reset();
+ _spellLevel.reset();
}
void Character::updateAC() {
@@ -344,6 +344,64 @@ void Character::updateAC() {
_ac._current = ac;
}
+void Character::updateSP() {
+ int intelligence = _intelligence._current;
+ int personality = _personality._current;
+ int level = _level._current;
+ int index = 3;
+ AttributePair newSP;
+
+ // Spell points only relevant for spell casters
+ if (_spellLevel._current) {
+ int threshold = -1;
+ if (_class == CLERIC)
+ threshold = personality;
+ else if (_class == SORCERER)
+ threshold = intelligence;
+ else if (level < 7)
+ threshold = -1;
+ else {
+ level -= 6;
+ threshold = (_class == PALADIN) ?
+ personality : intelligence;
+ }
+
+ if (threshold >= 40)
+ index += 10;
+ else if (threshold >= 35)
+ index += 9;
+ else if (threshold >= 30)
+ index += 8;
+ else if (threshold >= 27)
+ index += 7;
+ else if (threshold >= 24)
+ index += 6;
+ else if (threshold >= 21)
+ index += 5;
+ else if (threshold >= 19)
+ index += 4;
+ else if (threshold >= 17)
+ index += 3;
+ else if (threshold >= 15)
+ index += 2;
+ else if (threshold >= 13)
+ index += 1;
+ else if (threshold < 5)
+ index -= 3;
+ else if (threshold < 7)
+ index -= 2;
+ else if (threshold < 9)
+ index -= 1;
+
+ // Calculate the SP
+ newSP._base += index * level;
+ newSP._current = newSP._base;
+ }
+
+ // Set the character's new SP
+ _sp = newSP;
+}
+
Common::String Character::getConditionString() const {
Common::String result;
int cond = _condition;
@@ -386,5 +444,16 @@ void Character::castUnknown() {
warning("TODO: castUnknown method");
}
+void Character::rest() {
+ // Characters with a bad condition like
+ // being stoned can't rest
+ if (_condition & BAD_CONDITION)
+ return;
+
+ updateSP();
+
+ // TODO: More stuff
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index b89ac6db680..c7b5b4d91da 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -183,7 +183,7 @@ struct Character {
AttributePair _level;
AttributePair _age;
AttributePair _sp;
- AttributePair _slvl;
+ AttributePair _spellLevel;
AttributePair _ac;
byte _v2c = 0;
@@ -261,12 +261,22 @@ struct Character {
*/
void updateAC();
+ /**
+ * Updates the character's SP
+ */
+ void updateSP();
+
/**
* Gets a character's condition string
*/
Common::String getConditionString() const;
void castUnknown();
+
+ /**
+ * Rest the character
+ */
+ void rest();
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/rest.cpp b/engines/mm/mm1/game/rest.cpp
index 0798e24a34b..c24b0a589be 100644
--- a/engines/mm/mm1/game/rest.cpp
+++ b/engines/mm/mm1/game/rest.cpp
@@ -20,15 +20,47 @@
*/
#include "mm/mm1/events.h"
-#include "mm/mm1/sound.h"
+#include "mm/mm1/mm1.h"
#include "mm/mm1/game/rest.h"
+#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/maps/maps.h"
namespace MM {
namespace MM1 {
namespace Game {
+void Rest::check() {
+ int dangerRate = g_maps->_currentMap->dataByte(44);
+ if (!dangerRate ||
+ g_engine->getRandomNumber(dangerRate) != dangerRate) {
+ // Rest allowed
+ execute();
+ } else {
+ // Choose a random character, and make everyone
+ // but them be asleep
+ uint awakeIndex = g_engine->getRandomNumber(
+ g_globals->_party.size() - 1);
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c._condition >= 0 && i != awakeIndex)
+ c._condition |= ASLEEP;
+ }
+
+ // Start an encounter
+ Game::Encounter::execute();
+ }
+}
+
void Rest::execute() {
- // TODO: Handle properly
+ // Reset active spells
+ Common::fill(&g_globals->_spells._arr[0],
+ &g_globals->_spells._arr[ACTIVE_SPELLS_COUNT], 0);
+
+ // Rest the characters of the party
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c.rest();
+ }
}
} // namespace Game
diff --git a/engines/mm/mm1/game/rest.h b/engines/mm/mm1/game/rest.h
index d4c322b3206..068582bf972 100644
--- a/engines/mm/mm1/game/rest.h
+++ b/engines/mm/mm1/game/rest.h
@@ -27,6 +27,15 @@ namespace MM1 {
namespace Game {
struct Rest {
+ /**
+ * Checks the current map to see whether the
+ * party is able to rest, or an encounter is triggered
+ */
+ static void check();
+
+ /**
+ * Handles the rest
+ */
static void execute();
};
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/cast_spell.cpp
index 7264a497f93..8cf9b80044a 100644
--- a/engines/mm/mm1/views/cast_spell.cpp
+++ b/engines/mm/mm1/views/cast_spell.cpp
@@ -34,7 +34,7 @@ CastSpell::CastSpell() : TextView("CastSpell") {
bool CastSpell::msgValue(const ValueMessage &msg) {
if (msg._value == 0) {
// Ensure current character can cast spells
- if (g_globals->_currCharacter->_slvl != 0 &&
+ if (g_globals->_currCharacter->_spellLevel != 0 &&
g_globals->_currCharacter->_sp != 0) {
addView();
setState(SELECT_SPELL);
@@ -126,7 +126,7 @@ void CastSpell::draw() {
void CastSpell::spellLevelEntered(uint level) {
// Ensure the spell level is valid
if (level < 1 || level > 7 ||
- level > g_globals->_currCharacter->_slvl) {
+ level > g_globals->_currCharacter->_spellLevel) {
close();
return;
}
diff --git a/engines/mm/mm1/views/character_base.cpp b/engines/mm/mm1/views/character_base.cpp
index 63ae8fd22e7..2fd99a6138c 100644
--- a/engines/mm/mm1/views/character_base.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -59,7 +59,7 @@ void CharacterBase::printStats() {
writeNumber(re._sp._base);
_textPos.x = 22;
writeChar('(');
- writeNumber(re._slvl._current);
+ writeNumber(re._spellLevel._current);
writeChar(')');
_textPos.x = 26;
writeString(STRING["stats.attributes.gems"]);
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index c4adc6aaa59..24545cae0fd 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -176,7 +176,7 @@ void CreateCharacters::NewCharacter::setSP(int amount) {
level = 1;
re._sp = level + 3;
- re._slvl = 1;
+ re._spellLevel = 1;
}
/*------------------------------------------------------------------------*/
diff --git a/engines/mm/mm1/views/rest.cpp b/engines/mm/mm1/views/rest.cpp
index 74dfa7d0a3a..d8ea5d6d8ff 100644
--- a/engines/mm/mm1/views/rest.cpp
+++ b/engines/mm/mm1/views/rest.cpp
@@ -45,6 +45,7 @@ bool Rest::msgFocus(const FocusMessage &msg) {
_mode = CONFIRM;
if (g_maps->_currentState & 8)
tooDangerous();
+ return true;
}
void Rest::draw() {
@@ -60,8 +61,8 @@ bool Rest::msgKeypress(const KeypressMessage &msg) {
msg.keycode == Common::KEYCODE_n) {
close();
} else if (msg.keycode == Common::KEYCODE_y) {
- Game::Rest::execute();
- restComplete();
+ close();
+ Game::Rest::check();
}
}
@@ -69,19 +70,12 @@ bool Rest::msgKeypress(const KeypressMessage &msg) {
}
void Rest::tooDangerous() {
- _mode = RESPONSE;
+ _mode = TOO_DANGEROUS;
clearSurface();
writeString(2, 0, STRING["dialogs.game.rest.too_dangerous"]);
delaySeconds(3);
}
-void Rest::restComplete() {
- _mode = RESPONSE;
- clearSurface();
- writeString(0, 0, STRING["dialogs.game.rest.rest_complete"]);
- delaySeconds(3);
-}
-
void Rest::timeout() {
close();
}
diff --git a/engines/mm/mm1/views/rest.h b/engines/mm/mm1/views/rest.h
index a91b22e3491..85c3effe68d 100644
--- a/engines/mm/mm1/views/rest.h
+++ b/engines/mm/mm1/views/rest.h
@@ -30,11 +30,10 @@ namespace Views {
class Rest : public TextView {
private:
- enum Mode { CONFIRM, RESPONSE };
+ enum Mode { CONFIRM, TOO_DANGEROUS };
Mode _mode = CONFIRM;
void tooDangerous();
- void restComplete();
public:
Rest();
virtual ~Rest() {}
Commit: ed63d19db9c965c5c0829f321afa4191a450e51c
https://github.com/scummvm/scummvm/commit/ed63d19db9c965c5c0829f321afa4191a450e51c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Implemented update58 method
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/views/create_characters.cpp
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 3a14123c11b..45325bb4a8c 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -30,6 +30,11 @@ static const int CLASS_HP_PER_LEVEL[6] = {
12, 10, 10, 8, 6, 8
};
+Arr58::Arr58() {
+ for (int i = 0; i < 8; ++i)
+ _arr[i].clear();
+}
+
void Inventory::clear() {
_items.clear();
_items.resize(INVENTORY_COUNT);
@@ -167,8 +172,11 @@ void Character::clear() {
_alignmentInitial = GOOD;
_alignment = GOOD;
- _v58 = _v59 = _v62 = _v63 = _v64 = _v65 = 0;
- _v66 = _v67 = _v6c = _v6f = 0;
+ _arr58._s._v58.clear();
+ _arr58._s._v62.clear();
+ _arr58._s._v64.clear();
+ _arr58._s._v66.clear();
+ _v6c = _v6f = 0;
}
@@ -402,6 +410,11 @@ void Character::updateSP() {
_sp = newSP;
}
+void Character::update58() {
+ for (int i = 0; i < 8; ++i)
+ _arr58._arr[i]._current = _arr58._arr[i]._base;
+}
+
Common::String Character::getConditionString() const {
Common::String result;
int cond = _condition;
@@ -451,6 +464,14 @@ void Character::rest() {
return;
updateSP();
+ updateAttributes();
+ updateAC();
+ update58();
+
+ _condition &= ~(ASLEEP | BLINDED | SILENCED |
+ PARALYZED | UNCONSCIOUS);
+
+// if (_hpBase == 0 && )
// TODO: More stuff
}
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index c7b5b4d91da..3ea3d7280a2 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -164,6 +164,31 @@ struct AttributePair {
}
};
+struct AttributePair16 {
+ uint16 _current = 0;
+ uint16 _base = 0;
+
+ void clear() { _current = _base = 0; }
+};
+
+struct Arr58Fields {
+ AttributePair _v58;
+ AttributePair _v5a;
+ AttributePair _v5c;
+ AttributePair _v5e;
+ AttributePair _v60;
+ AttributePair _v62;
+ AttributePair _v64;
+ AttributePair _v66;
+};
+
+union Arr58 {
+ Arr58Fields _s;
+ AttributePair _arr[8];
+
+ Arr58();
+};
+
struct Character {
char _name[16] = { 0 };
Sex _sex = MALE;
@@ -198,9 +223,8 @@ struct Character {
Inventory _backpack;
// TODO: Figure out what these are
- int _v58, _v59, _v62, _v63, _v64, _v65;
- int _v66, _v67, _v68, _v69, _v6a, _v6b,
- _v6c, _v6e, _v6f;
+ Arr58 _arr58;
+ int _v68, _v69, _v6a, _v6b, _v6c, _v6e, _v6f;
byte _quest = 0;
@@ -266,6 +290,8 @@ struct Character {
*/
void updateSP();
+ void update58();
+
/**
* Gets a character's condition string
*/
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 24545cae0fd..93695679074 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -106,20 +106,20 @@ void CreateCharacters::NewCharacter::save() {
switch (_race) {
case HUMAN:
- re._v62 = re._v63 = 70;
- re._v66 = re._v67 = 25;
+ re._arr58._s._v62 = 70;
+ re._arr58._s._v66 = 25;
break;
case ELF:
- re._v62 = re._v63 = 70;
+ re._arr58._s._v62 = 70;
break;
case DWARF:
- re._v64 = re._v65 = 25;
+ re._arr58._s._v64 = 25;
break;
case GNOME:
- re._v58 = re._v59 = 20;
+ re._arr58._s._v58 = 20;
break;
case HALF_ORC:
- re._v66 = re._v67 = 50;
+ re._arr58._s._v66 = 50;
break;
}
Commit: a1dd06df3ffd1f5dbb1c318ad332c57e8ddc26e2
https://github.com/scummvm/scummvm/commit/a1dd06df3ffd1f5dbb1c318ad332c57e8ddc26e2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Finished Character::rest method
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/views/cast_spell.cpp
engines/mm/mm1/views/quick_ref.cpp
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 45325bb4a8c..7a74f0d8d46 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -114,10 +114,8 @@ void Character::synchronize(Common::Serializer &s) {
_age.synchronize(s);
s.syncAsUint32LE(_exp);
- s.syncAsByte(_sp._current);
- s.syncAsByte(_v2c);
- s.syncAsByte(_sp._base);
- s.syncAsByte(_v2e);
+ s.syncAsUint16LE(_sp._current);
+ s.syncAsUint16LE(_sp._base);
_spellLevel.synchronize(s);
s.syncAsUint16LE(_gems);
@@ -471,9 +469,54 @@ void Character::rest() {
_condition &= ~(ASLEEP | BLINDED | SILENCED |
PARALYZED | UNCONSCIOUS);
-// if (_hpBase == 0 && )
+ if (_hpBase == 0)
+ _hpBase = 1;
- // TODO: More stuff
+ if (_age._current++ == 255) {
+ _age._base = MIN((int)_age._base + 1, 255);
+ }
+ if ((g_engine->getRandomNumber(70) + 80) < _age._base) {
+ _condition = UNCONSCIOUS | BAD_CONDITION;
+ return;
+ }
+
+ if (_age._base >= 60) {
+ // Fun fact: in the original if any of the attributes
+ // reach zero, then it jumps to an instruction that
+ // jumps to itself, freezing the game.
+ if (--_might._current == 0 ||
+ --_endurance._current == 0 ||
+ --_speed._current == 0)
+ error("Attributes bottomed out during rest");
+
+ if (_age._base >= 70) {
+ if (--_might._current == 0 ||
+ --_endurance._current == 0 ||
+ --_speed._current == 0)
+ error("Attributes bottomed out during rest");
+ }
+
+ if (_age._base >= 80) {
+ if (_might._current <= 2)
+ error("Attributes bottomed out during rest");
+ _might._current -= 2;
+ }
+ }
+
+ if (_food > 0) {
+ --_food;
+
+ if (_condition & POISONED) {
+ _hpMax /= 2;
+ } else {
+ _hpMax = _hp;
+ }
+
+ if (_condition & DISEASED) {
+ _hpBase = _hpMax;
+ _sp._current = _sp._base;
+ }
+ }
}
} // namespace MM1
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 3ea3d7280a2..564bce0c074 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -169,6 +169,14 @@ struct AttributePair16 {
uint16 _base = 0;
void clear() { _current = _base = 0; }
+ AttributePair16 &operator=(byte v) {
+ _base = _current = v;
+ return *this;
+ }
+ void synchronize(Common::Serializer &s) {
+ s.syncAsUint16LE(_base);
+ s.syncAsUint16LE(_current);
+ }
};
struct Arr58Fields {
@@ -207,12 +215,10 @@ struct Character {
AttributePair _level;
AttributePair _age;
- AttributePair _sp;
+ AttributePair16 _sp;
AttributePair _spellLevel;
AttributePair _ac;
- byte _v2c = 0;
- byte _v2e = 0;
uint32 _exp = 0;
uint16 _gems = 0;
uint16 _hpBase = 0, _hp = 0, _hpMax = 0;
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 4e96460a8ea..4744830eafa 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -95,7 +95,7 @@ void SpellCasting::setSpell(Character *chr, int lvl, int num) {
// required SP increases with character's level
requiredSp = chr->_level;
- if (!chr->_v2c) {
+ if (!chr->_sp._current) {
if (SPELLS_SP_GEMS[spellIndex] < 0 && chr->_sp._current < chr->_level._current)
_spellState = SS_NOT_ENOUGH_SP;
else if ((lvl - 1) > chr->_sp._current)
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/cast_spell.cpp
index 8cf9b80044a..a27ac3d8710 100644
--- a/engines/mm/mm1/views/cast_spell.cpp
+++ b/engines/mm/mm1/views/cast_spell.cpp
@@ -35,7 +35,7 @@ bool CastSpell::msgValue(const ValueMessage &msg) {
if (msg._value == 0) {
// Ensure current character can cast spells
if (g_globals->_currCharacter->_spellLevel != 0 &&
- g_globals->_currCharacter->_sp != 0) {
+ g_globals->_currCharacter->_sp._current != 0) {
addView();
setState(SELECT_SPELL);
}
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index 124e02b7cd2..c29f80a032a 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -48,7 +48,7 @@ void QuickRef::draw() {
// Spell points
_textPos.x = 28;
- writeNumber(c._sp);
+ writeNumber(c._sp._current);
_textPos.x = 32;
writeChar('/');
writeNumber(c._sp._base);
Commit: cdbe936eb9fed6ed43d32a186101478fe55a9b82
https://github.com/scummvm/scummvm/commit/cdbe936eb9fed6ed43d32a186101478fe55a9b82
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:06+01:00
Commit Message:
MM: MM1: Hook up rest in-game action
Changed paths:
engines/mm/mm1/game/rest.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/rest.cpp
diff --git a/engines/mm/mm1/game/rest.cpp b/engines/mm/mm1/game/rest.cpp
index c24b0a589be..065bf62753a 100644
--- a/engines/mm/mm1/game/rest.cpp
+++ b/engines/mm/mm1/game/rest.cpp
@@ -61,6 +61,10 @@ void Rest::execute() {
Character &c = g_globals->_party[i];
c.rest();
}
+
+ g_events->send(InfoMessage(
+ STRING["dialogs.game.rest.rest_complete"]
+ ));
}
} // namespace Game
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 4ede3413321..4657d05b6de 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -36,6 +36,7 @@
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/encounter.h"
+#include "mm/mm1/views/rest.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/views/locations/market.h"
@@ -60,6 +61,7 @@ private:
Views::Order _order;
Views::Protect _protect;
Views::QuickRef _quickRef;
+ Views::Rest _rest;
Views::Title _title;
Views::CharacterInfo _characterInfo;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 135b9bf9eee..391055eeb5e 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -56,6 +56,9 @@ bool Game::msgAction(const ActionMessage &msg) {
case KEYBIND_QUICKREF:
addView("QuickRef");
return true;
+ case KEYBIND_REST:
+ g_events->send(GameMessage("REST"));
+ return true;
case KEYBIND_SEARCH:
MM1::Game::Search::execute();
break;
diff --git a/engines/mm/mm1/views/rest.cpp b/engines/mm/mm1/views/rest.cpp
index d8ea5d6d8ff..7752f27e8f6 100644
--- a/engines/mm/mm1/views/rest.cpp
+++ b/engines/mm/mm1/views/rest.cpp
@@ -32,7 +32,7 @@ Rest::Rest() : TextView("Rest") {
}
bool Rest::msgGame(const GameMessage &msg) {
- if (msg._name == "Rest") {
+ if (msg._name == "REST") {
// Show the dialog
addView(this);
return true;
Commit: eb18aaa1579e7d800a44e8dd0ec3889916801333
https://github.com/scummvm/scummvm/commit/eb18aaa1579e7d800a44e8dd0ec3889916801333
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: Added shelter spell
Changed paths:
engines/mm/mm1/data/spells.cpp
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 28134b371f1..1d123eb2c30 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/data/spells.h"
#include "mm/mm1/data/locations.h"
+#include "mm/mm1/game/rest.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
@@ -542,7 +543,11 @@ SpellResult Spells::wizard46_psychicProtection(Character *chr) {
}
SpellResult Spells::wizard54_shelter(Character *chr) {
- return SR_FAILED;
+ if (g_maps->_currentState & 8)
+ return SR_FAILED;
+
+ Game::Rest::execute();
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard55_teleport(Character *chr) {
Commit: f370da260ad818a597919244ab3d9537f5beb734
https://github.com/scummvm/scummvm/commit/f370da260ad818a597919244ab3d9537f5beb734
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: Adding teleport spell view
Changed paths:
A engines/mm/mm1/views/spells/teleport.cpp
A engines/mm/mm1/views/spells/teleport.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index f42a114f7c1..81c2528d271 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -254,6 +254,8 @@
spells:
fly_to_x: "FLY TO (A-E): "
fly_to_y: "(1-4): "
+ teleport_dir: "DIRECTION (N,E,S,W): "
+ teleport_squares: "# OF SQUARES (0-9): "
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 1d123eb2c30..39f9caaeb32 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -26,6 +26,7 @@
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
#include "mm/mm1/views/spells/fly.h"
+#include "mm/mm1/views/spells/teleport.h"
namespace MM {
namespace MM1 {
@@ -551,7 +552,8 @@ SpellResult Spells::wizard54_shelter(Character *chr) {
}
SpellResult Spells::wizard55_teleport(Character *chr) {
- return SR_FAILED;
+ Views::Spells::Teleport::show();
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard63_etherialize(Character *chr) {
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 4657d05b6de..ef32e67c08d 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -45,6 +45,7 @@
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/views/spells/fly.h"
+#include "mm/mm1/views/spells/teleport.h"
namespace MM {
namespace MM1 {
@@ -74,6 +75,7 @@ private:
Views::Locations::Training _training;
Views::Spells::Fly _flySpell;
+ Views::Spells::Teleport _telportSpell;
public:
Dialogs() {}
};
diff --git a/engines/mm/mm1/views/spells/teleport.cpp b/engines/mm/mm1/views/spells/teleport.cpp
new file mode 100644
index 00000000000..064deb68764
--- /dev/null
+++ b/engines/mm/mm1/views/spells/teleport.cpp
@@ -0,0 +1,122 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/spells/teleport.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+void Teleport::show() {
+ Teleport *teleport = dynamic_cast<Teleport *>(g_events->findView("Teleport"));
+ assert(teleport);
+
+ teleport->focus();
+}
+
+Teleport::Teleport() : TextView("Teleport") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Teleport::msgFocus(const FocusMessage &) {
+ _mode = SELECT_DIRECTION;
+ return 0;
+}
+
+void Teleport::draw() {
+ clearSurface();
+ escToGoBack(0);
+
+ clearSurface();
+ escToGoBack(0);
+
+ writeString(10, 0, STRING["dialogs.spells.teleport_dir"]);
+ writeChar((_mode == SELECT_DIRECTION) ? '_' : _direction);
+
+ if (_mode != SELECT_DIRECTION) {
+ writeString(11, 1, STRING["dialogs.spells.teleport_squares"]);
+ writeChar((_mode == CAST) ? '_' : '0' + _squares);
+ }
+
+ if (_mode == CAST)
+ writeString(23, 4, STRING["spells.enter_to_cast"]);
+}
+
+bool Teleport::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+
+ } else if (_mode == SELECT_DIRECTION && (
+ msg.keycode == Common::KEYCODE_n ||
+ msg.keycode == Common::KEYCODE_s ||
+ msg.keycode == Common::KEYCODE_e ||
+ msg.keycode == Common::KEYCODE_w)) {
+ _direction = toupper(msg.ascii);
+ _mode = SELECT_SQUARES;
+ redraw();
+
+ } else if (_mode == SELECT_SQUARES && (
+ msg.keycode >= Common::KEYCODE_0 &&
+ msg.keycode <= Common::KEYCODE_9)) {
+ _squares = msg.keycode - Common::KEYCODE_0;
+ _mode = CAST;
+ redraw();
+
+ } else if (_mode == CAST && Common::KEYCODE_RETURN) {
+ teleport();
+ }
+
+ return true;
+}
+
+void Teleport::teleport() {
+ Maps::Maps &maps = *g_maps;
+ Maps::Map &map = *maps._currentMap;
+
+ if (map[46] & 2) {
+ // Given map doesn't allow teleporting
+ error("TODO: spell failed");
+ } else {
+ switch (_direction) {
+ case 'N':
+ maps.step(Common::Point(0, _squares));
+ break;
+ case 'S':
+ maps.step(Common::Point(0, -_squares));
+ break;
+ case 'E':
+ maps.step(Common::Point(_squares, 0));
+ break;
+ case 'W':
+ maps.step(Common::Point(-_squares, 0));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/spells/teleport.h b/engines/mm/mm1/views/spells/teleport.h
new file mode 100644
index 00000000000..136a09a8d29
--- /dev/null
+++ b/engines/mm/mm1/views/spells/teleport.h
@@ -0,0 +1,82 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SPELLS_TELEPORT_H
+#define MM1_VIEWS_SPELLS_TELEPORT_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+class Teleport : public TextView {
+private:
+ enum Mode {
+ SELECT_DIRECTION, SELECT_SQUARES, CAST
+ };
+ Mode _mode = SELECT_DIRECTION;
+ char _direction = '\0';
+ int _squares = 0;
+
+ /**
+ * Handle the teleporting
+ */
+ void teleport();
+public:
+ /**
+ * Show the view
+ */
+ static void show();
+public:
+ /**
+ * Constructor
+ */
+ Teleport();
+
+ /**
+ * Destructor
+ */
+ virtual ~Teleport() {}
+
+ /**
+ * Show the view
+ */
+ bool msgFocus(const FocusMessage &) override;
+
+ /**
+ * Draw the view contents
+ */
+ void draw() override;
+
+ /**
+ * Keypress handler
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 826bf7dff9d..4ef32a51567 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -45,6 +45,7 @@ MODULE_OBJS := \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
mm1/views/spells/fly.o \
+ mm1/views/spells/teleport.o \
mm1/views/are_you_ready.o \
mm1/views/cast_spell.o \
mm1/views/character_base.o \
Commit: 1913a5fa2e5e2fae0ae216732fad8c876226bf87
https://github.com/scummvm/scummvm/commit/1913a5fa2e5e2fae0ae216732fad8c876226bf87
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: Move CastSpell view to spells/ subfolder
Changed paths:
A engines/mm/mm1/views/spells/cast_spell.cpp
A engines/mm/mm1/views/spells/cast_spell.h
R engines/mm/mm1/views/cast_spell.cpp
R engines/mm/mm1/views/cast_spell.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index ef32e67c08d..35bf3bf8fef 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -32,7 +32,6 @@
#include "mm/mm1/views/protect.h"
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
-#include "mm/mm1/views/cast_spell.h"
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/encounter.h"
@@ -44,6 +43,7 @@
#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
+#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/views/spells/fly.h"
#include "mm/mm1/views/spells/teleport.h"
@@ -54,7 +54,6 @@ namespace Views {
struct Dialogs {
private:
Views::AreYouReady _areYouReady;
- Views::CastSpell _castSpell;
Views::CreateCharacters _createCharacters;
Views::Encounter _encounter;
Views::Game _game;
@@ -74,6 +73,7 @@ private:
Views::Locations::Temple _temple;
Views::Locations::Training _training;
+ Views::Spells::CastSpell _castSpell;
Views::Spells::Fly _flySpell;
Views::Spells::Teleport _telportSpell;
public:
diff --git a/engines/mm/mm1/views/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
similarity index 95%
rename from engines/mm/mm1/views/cast_spell.cpp
rename to engines/mm/mm1/views/spells/cast_spell.cpp
index a27ac3d8710..23ae254ea15 100644
--- a/engines/mm/mm1/views/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -19,13 +19,14 @@
*
*/
-#include "mm/mm1/views/cast_spell.h"
+#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
namespace Views {
+namespace Spells {
CastSpell::CastSpell() : TextView("CastSpell") {
_bounds = getLineBounds(20, 24);
@@ -85,7 +86,7 @@ void CastSpell::draw() {
(CastSpell *)g_events->focusedView();
view->spellLevelEntered(atoi(text.c_str()));
}
- );
+ );
break;
case SELECT_NUMBER:
@@ -103,7 +104,7 @@ void CastSpell::draw() {
(CastSpell *)g_events->focusedView();
view->spellNumberEntered(atoi(text.c_str()));
}
- );
+ );
break;
case SELECT_CHAR:
@@ -167,8 +168,8 @@ bool CastSpell::msgKeypress(const KeypressMessage &msg) {
bool CastSpell::msgAction(const ActionMessage &msg) {
if (_state == SELECT_CHAR &&
- msg._action >= KEYBIND_VIEW_PARTY1 &&
- msg._action <= KEYBIND_VIEW_PARTY6) {
+ msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
uint charIndex = (int)(msg._action - KEYBIND_VIEW_PARTY1);
if (charIndex < g_globals->_party.size())
performSpell(&g_globals->_party[charIndex]);
@@ -193,7 +194,7 @@ void CastSpell::performSpell(Character *chr) {
spellDone(STRING["dialogs.misc.magic_doesnt_work"], 5);
} else {
// Cast the spell
- switch (Spells::cast(_spellIndex, chr)) {
+ switch (MM1::Spells::cast(_spellIndex, chr)) {
case SR_FAILED:
// Spell failed
clearSurface();
@@ -242,6 +243,7 @@ void CastSpell::spellDone(const Common::String &msg, int xp) {
delaySeconds(3);
}
+} // namespace Spells
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/cast_spell.h b/engines/mm/mm1/views/spells/cast_spell.h
similarity index 96%
rename from engines/mm/mm1/views/cast_spell.h
rename to engines/mm/mm1/views/spells/cast_spell.h
index 50ff89d31b6..9dec7b80e24 100644
--- a/engines/mm/mm1/views/cast_spell.h
+++ b/engines/mm/mm1/views/spells/cast_spell.h
@@ -29,6 +29,7 @@
namespace MM {
namespace MM1 {
namespace Views {
+namespace Spells {
class CastSpell : public TextView, public MM1::Game::SpellCasting {
enum State {
@@ -67,7 +68,8 @@ private:
void spellDone(const Common::String &msg, int xp);
public:
CastSpell();
- virtual ~CastSpell() {}
+ virtual ~CastSpell() {
+ }
bool msgValue(const ValueMessage &msg) override;
void draw() override;
@@ -76,6 +78,7 @@ public:
void timeout() override;
};
+} // namespace Spells
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 4ef32a51567..d0d8cd06818 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -44,10 +44,10 @@ MODULE_OBJS := \
mm1/views/locations/tavern.o \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
+ mm1/views/spells/cast_spell.o \
mm1/views/spells/fly.o \
mm1/views/spells/teleport.o \
mm1/views/are_you_ready.o \
- mm1/views/cast_spell.o \
mm1/views/character_base.o \
mm1/views/character_info.o \
mm1/views/character_manage.o \
Commit: 4c7357bcfbe3c29cd21923620c26212c22cf01ef
https://github.com/scummvm/scummvm/commit/4c7357bcfbe3c29cd21923620c26212c22cf01ef
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: SpellView base class for spell dialogs
Changed paths:
A engines/mm/mm1/views/spells/spell_view.cpp
A engines/mm/mm1/views/spells/spell_view.h
engines/mm/mm1/views/spells/cast_spell.cpp
engines/mm/mm1/views/spells/cast_spell.h
engines/mm/mm1/views/spells/fly.cpp
engines/mm/mm1/views/spells/fly.h
engines/mm/mm1/views/spells/teleport.cpp
engines/mm/mm1/views/spells/teleport.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index 23ae254ea15..a7d895a648f 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -28,7 +28,7 @@ namespace MM1 {
namespace Views {
namespace Spells {
-CastSpell::CastSpell() : TextView("CastSpell") {
+CastSpell::CastSpell() : SpellView("CastSpell") {
_bounds = getLineBounds(20, 24);
}
@@ -197,21 +197,12 @@ void CastSpell::performSpell(Character *chr) {
switch (MM1::Spells::cast(_spellIndex, chr)) {
case SR_FAILED:
// Spell failed
- clearSurface();
- writeString(10, 2, STRING["spells.failed"]);
-
- Sound::sound(SOUND_2);
- delaySeconds(3);
+ spellFailed();
break;
case SR_SUCCESS_DONE:
// Display spell done
- clearSurface();
- writeString(14, 2, STRING["dialogs.misc.done"]);
- g_globals->_party.updateAC();
-
- Sound::sound(SOUND_2);
- delaySeconds(3);
+ spellDone();
break;
default:
diff --git a/engines/mm/mm1/views/spells/cast_spell.h b/engines/mm/mm1/views/spells/cast_spell.h
index 9dec7b80e24..c567a53d0c6 100644
--- a/engines/mm/mm1/views/spells/cast_spell.h
+++ b/engines/mm/mm1/views/spells/cast_spell.h
@@ -19,10 +19,10 @@
*
*/
-#ifndef MM1_VIEWS_CAST_SPELL_H
-#define MM1_VIEWS_CAST_SPELL_H
+#ifndef MM1_VIEWS_SPELLS_CAST_SPELL_H
+#define MM1_VIEWS_SPELLS_CAST_SPELL_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/spells/spell_view.h"
#include "mm/mm1/views/text_entry.h"
#include "mm/mm1/game/spell_casting.h"
@@ -31,7 +31,7 @@ namespace MM1 {
namespace Views {
namespace Spells {
-class CastSpell : public TextView, public MM1::Game::SpellCasting {
+class CastSpell : public SpellView, public MM1::Game::SpellCasting {
enum State {
SELECT_SPELL, SELECT_NUMBER, SELECT_CHAR, PRESS_ENTER,
ENDING
diff --git a/engines/mm/mm1/views/spells/fly.cpp b/engines/mm/mm1/views/spells/fly.cpp
index 5e01b40ad68..e87fb2a4239 100644
--- a/engines/mm/mm1/views/spells/fly.cpp
+++ b/engines/mm/mm1/views/spells/fly.cpp
@@ -35,7 +35,7 @@ void Fly::show(FlyCallback callback) {
fly->focus();
}
-Fly::Fly() : TextView("Fly") {
+Fly::Fly() : SpellView("Fly") {
_bounds = getLineBounds(21, 24);
}
diff --git a/engines/mm/mm1/views/spells/fly.h b/engines/mm/mm1/views/spells/fly.h
index c868c4a4732..7d178eb8bcc 100644
--- a/engines/mm/mm1/views/spells/fly.h
+++ b/engines/mm/mm1/views/spells/fly.h
@@ -22,7 +22,7 @@
#ifndef MM1_VIEWS_SPELLS_FLY_H
#define MM1_VIEWS_SPELLS_FLY_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/spells/spell_view.h"
namespace MM {
namespace MM1 {
@@ -35,7 +35,7 @@ namespace Spells {
*/
typedef void (*FlyCallback)(int mapId);
-class Fly : public TextView {
+class Fly : public SpellView {
private:
FlyCallback _callback;
enum Mode {
diff --git a/engines/mm/mm1/views/spells/spell_view.cpp b/engines/mm/mm1/views/spells/spell_view.cpp
new file mode 100644
index 00000000000..54fead8aebd
--- /dev/null
+++ b/engines/mm/mm1/views/spells/spell_view.cpp
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/spells/spell_view.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+void SpellView::spellFailed() {
+ // Spell failed
+ clearSurface();
+ writeString(10, 2, STRING["spells.failed"]);
+
+ Sound::sound(SOUND_2);
+ delaySeconds(3);
+}
+
+void SpellView::spellDone() {
+ clearSurface();
+ writeString(14, 2, STRING["dialogs.misc.done"]);
+ g_globals->_party.updateAC();
+
+ Sound::sound(SOUND_2);
+ delaySeconds(3);
+}
+
+void SpellView::timeout() {
+ close();
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/spells/spell_view.h b/engines/mm/mm1/views/spells/spell_view.h
new file mode 100644
index 00000000000..ecb6d273402
--- /dev/null
+++ b/engines/mm/mm1/views/spells/spell_view.h
@@ -0,0 +1,61 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SPELLS_SPELL_VIEW_H
+#define MM1_VIEWS_SPELLS_SPELL_VIEW_H
+
+#include "common/str.h"
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+class SpellView : public TextView {
+public:
+ SpellView(const Common::String &name) : TextView(name) {}
+ SpellView(const Common::String &name, UIElement *owner) :
+ TextView(name, owner) {}
+ virtual ~SpellView() {}
+
+ /**
+ * Spell failed display
+ */
+ void spellFailed();
+
+ /**
+ * Spell done display
+ */
+ void spellDone();
+
+ /**
+ * Timeout for the failed/done display
+ */
+ void timeout() override;
+};
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/spells/teleport.cpp b/engines/mm/mm1/views/spells/teleport.cpp
index 064deb68764..c1691a3fef0 100644
--- a/engines/mm/mm1/views/spells/teleport.cpp
+++ b/engines/mm/mm1/views/spells/teleport.cpp
@@ -34,7 +34,7 @@ void Teleport::show() {
teleport->focus();
}
-Teleport::Teleport() : TextView("Teleport") {
+Teleport::Teleport() : SpellView("Teleport") {
_bounds = getLineBounds(20, 24);
}
diff --git a/engines/mm/mm1/views/spells/teleport.h b/engines/mm/mm1/views/spells/teleport.h
index 136a09a8d29..bd7c0d5fec4 100644
--- a/engines/mm/mm1/views/spells/teleport.h
+++ b/engines/mm/mm1/views/spells/teleport.h
@@ -22,14 +22,14 @@
#ifndef MM1_VIEWS_SPELLS_TELEPORT_H
#define MM1_VIEWS_SPELLS_TELEPORT_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/spells/spell_view.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Spells {
-class Teleport : public TextView {
+class Teleport : public SpellView {
private:
enum Mode {
SELECT_DIRECTION, SELECT_SQUARES, CAST
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index d0d8cd06818..a302fd368c2 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -44,6 +44,7 @@ MODULE_OBJS := \
mm1/views/locations/tavern.o \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
+ mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
mm1/views/spells/fly.o \
mm1/views/spells/teleport.o \
Commit: eaadd4025d6cd93af1840a081ef179a730448580
https://github.com/scummvm/scummvm/commit/eaadd4025d6cd93af1840a081ef179a730448580
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: Teleport spell now working
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/views/spells/fly.cpp
engines/mm/mm1/views/spells/spell_view.cpp
engines/mm/mm1/views/spells/spell_view.h
engines/mm/mm1/views/spells/teleport.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index fbb97582d76..d026dc5359f 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -151,6 +151,7 @@ public:
void addView(UIElement *ui);
void addView(const Common::String &name);
void addView();
+ void open() { addView(); }
/**
* Sets the element's bounds
diff --git a/engines/mm/mm1/views/spells/fly.cpp b/engines/mm/mm1/views/spells/fly.cpp
index e87fb2a4239..31c726a29be 100644
--- a/engines/mm/mm1/views/spells/fly.cpp
+++ b/engines/mm/mm1/views/spells/fly.cpp
@@ -32,14 +32,16 @@ void Fly::show(FlyCallback callback) {
assert(fly);
fly->_callback = callback;
- fly->focus();
+ fly->open();
}
Fly::Fly() : SpellView("Fly") {
_bounds = getLineBounds(21, 24);
}
-bool Fly::msgFocus(const FocusMessage &) {
+bool Fly::msgFocus(const FocusMessage &msg) {
+ SpellView::msgFocus(msg);
+
_mode = SELECT_X;
_xIndex = _yIndex = 0;
return 0;
diff --git a/engines/mm/mm1/views/spells/spell_view.cpp b/engines/mm/mm1/views/spells/spell_view.cpp
index 54fead8aebd..6100eacf38c 100644
--- a/engines/mm/mm1/views/spells/spell_view.cpp
+++ b/engines/mm/mm1/views/spells/spell_view.cpp
@@ -50,6 +50,11 @@ void SpellView::timeout() {
close();
}
+bool SpellView::msgFocus(const FocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return true;
+}
+
} // namespace Spells
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/spells/spell_view.h b/engines/mm/mm1/views/spells/spell_view.h
index ecb6d273402..6408a25d93c 100644
--- a/engines/mm/mm1/views/spells/spell_view.h
+++ b/engines/mm/mm1/views/spells/spell_view.h
@@ -51,6 +51,11 @@ public:
* Timeout for the failed/done display
*/
void timeout() override;
+
+ /**
+ * Called when the view is focused
+ */
+ bool msgFocus(const FocusMessage &msg) override;
};
} // namespace Spells
diff --git a/engines/mm/mm1/views/spells/teleport.cpp b/engines/mm/mm1/views/spells/teleport.cpp
index c1691a3fef0..7ca43a2abd4 100644
--- a/engines/mm/mm1/views/spells/teleport.cpp
+++ b/engines/mm/mm1/views/spells/teleport.cpp
@@ -28,17 +28,19 @@ namespace Views {
namespace Spells {
void Teleport::show() {
- Teleport *teleport = dynamic_cast<Teleport *>(g_events->findView("Teleport"));
+ UIElement *teleport = dynamic_cast<Teleport *>(g_events->findView("Teleport"));
assert(teleport);
- teleport->focus();
+ teleport->open();
}
Teleport::Teleport() : SpellView("Teleport") {
_bounds = getLineBounds(20, 24);
}
-bool Teleport::msgFocus(const FocusMessage &) {
+bool Teleport::msgFocus(const FocusMessage &msg) {
+ SpellView::msgFocus(msg);
+
_mode = SELECT_DIRECTION;
return 0;
}
@@ -50,12 +52,12 @@ void Teleport::draw() {
clearSurface();
escToGoBack(0);
- writeString(10, 0, STRING["dialogs.spells.teleport_dir"]);
+ writeString(10, 1, STRING["dialogs.spells.teleport_dir"]);
writeChar((_mode == SELECT_DIRECTION) ? '_' : _direction);
if (_mode != SELECT_DIRECTION) {
- writeString(11, 1, STRING["dialogs.spells.teleport_squares"]);
- writeChar((_mode == CAST) ? '_' : '0' + _squares);
+ writeString(11, 2, STRING["dialogs.spells.teleport_squares"]);
+ writeChar((_mode == SELECT_SQUARES) ? '_' : '0' + _squares);
}
if (_mode == CAST)
@@ -94,8 +96,8 @@ void Teleport::teleport() {
Maps::Map &map = *maps._currentMap;
if (map[46] & 2) {
- // Given map doesn't allow teleporting
- error("TODO: spell failed");
+ spellFailed();
+
} else {
switch (_direction) {
case 'N':
@@ -111,8 +113,11 @@ void Teleport::teleport() {
maps.step(Common::Point(-_squares, 0));
break;
default:
- break;
+ return;
}
+
+ close();
+ send("Game", GameMessage("UPDATE"));
}
}
Commit: 6d164f04d7ff4fc25785abca961b5fd281438919
https://github.com/scummvm/scummvm/commit/6d164f04d7ff4fc25785abca961b5fd281438919
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: Implemented location spell view
Changed paths:
A engines/mm/mm1/views/spells/location.cpp
A engines/mm/mm1/views/spells/location.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 81c2528d271..d569a21a52e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -256,6 +256,17 @@
fly_to_y: "(1-4): "
teleport_dir: "DIRECTION (N,E,S,W): "
teleport_squares: "# OF SQUARES (0-9): "
+ location_loc: "LOCATION: "
+ location_town: "IN TOWN"
+ location_castle: "IN CASTLE"
+ location_outdoors: "OUTDOORS"
+ location_unknown: "UNKNOWN"
+ location_under: "0' UNDER"
+ location_sector: "MAP SECTOR: "
+ location_surface_x: "SURFACE: X="
+ location_inside_x: "INSIDE: X="
+ location_facing: "FACING: "
+
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 39f9caaeb32..56b61412afa 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -26,6 +26,7 @@
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
#include "mm/mm1/views/spells/fly.h"
+#include "mm/mm1/views/spells/location.h"
#include "mm/mm1/views/spells/teleport.h"
namespace MM {
@@ -472,7 +473,8 @@ SpellResult Spells::wizard15_leatherSkin(Character *chr) {
}
SpellResult Spells::wizard17_location(Character *chr) {
- return SR_FAILED;
+ Views::Spells::Location::show();
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard24_jump(Character *chr) {
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 35bf3bf8fef..d7cfe312d6d 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -45,6 +45,7 @@
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/views/spells/fly.h"
+#include "mm/mm1/views/spells/location.h"
#include "mm/mm1/views/spells/teleport.h"
namespace MM {
@@ -75,6 +76,7 @@ private:
Views::Spells::CastSpell _castSpell;
Views::Spells::Fly _flySpell;
+ Views::Spells::Location _locationSpell;
Views::Spells::Teleport _telportSpell;
public:
Dialogs() {}
diff --git a/engines/mm/mm1/views/spells/location.cpp b/engines/mm/mm1/views/spells/location.cpp
new file mode 100644
index 00000000000..61e41db61fc
--- /dev/null
+++ b/engines/mm/mm1/views/spells/location.cpp
@@ -0,0 +1,111 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/spells/location.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+void Location::show() {
+ UIElement *view = dynamic_cast<Location *>(g_events->findView("Location"));
+ assert(view);
+
+ view->open();
+}
+
+Location::Location() : SpellView("Location") {
+ _bounds = getLineBounds(20, 24);
+}
+
+void Location::draw() {
+ Maps::Maps &maps = *g_maps;
+ Maps::Map &map = *maps._currentMap;
+ byte v;
+
+ clearSurface();
+ escToGoBack(0);
+
+ writeString(0, 0, STRING["dialogs.spells.location_loc"]);
+
+ v = map[37];
+ if (v == 0xff) {
+ writeString(STRING["dialogs.spells.location_unknown"]);
+ } else {
+ if (v == 0) {
+ writeString(STRING["dialogs.spells.location_outdoors"]);
+ } else if (!(v & 0x80)) {
+ writeChar('0' + map[37]);
+ writeString(STRING["dialogs.spells.location_undoor"]);
+ } else if (v == 0xfe) {
+ writeString(STRING["dialogs.spells.location_town"]);
+ } else {
+ writeString(STRING["dialogs.spells.location_castle"]);
+ }
+
+ writeString(21, 0, STRING["dialogs.spells.location_sector"]);
+ writeChar(map[35] & 0x7f);
+ writeChar('-');
+ writeChar(map[36] & 0x7f);
+
+ writeString(21, 1, STRING["dialogs.spells.location_surface_x"]);
+
+ if (map[37]) {
+ writeNumber(map[42]);
+ writeString(35, 1, "Y=");
+ writeNumber(map[43]);
+
+ writeString(22, 2, STRING["dialogs.spells.location_inside_x"]);
+ }
+
+ writeNumber(maps._mapPos.x);
+ writeString(35, 2, "Y=");
+ writeNumber(maps._mapPos.y);
+
+ writeString(22, 3, STRING["dialogs.spells.location_facing"]);
+ switch (maps._forwardMask) {
+ case Maps::DIRMASK_N:
+ writeChar('N');
+ break;
+ case Maps::DIRMASK_S:
+ writeChar('S');
+ break;
+ case Maps::DIRMASK_E:
+ writeChar('E');
+ break;
+ default:
+ writeChar('W');
+ break;
+ }
+ }
+}
+
+bool Location::msgKeypress(const KeypressMessage &msg) {
+ close();
+ return true;
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/spells/location.h b/engines/mm/mm1/views/spells/location.h
new file mode 100644
index 00000000000..103b0eb35f8
--- /dev/null
+++ b/engines/mm/mm1/views/spells/location.h
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SPELLS_LOCATION_H
+#define MM1_VIEWS_SPELLS_LOCATION_H
+
+#include "mm/mm1/views/spells/spell_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+class Location : public SpellView {
+public:
+ /**
+ * Show the view
+ */
+ static void show();
+public:
+ /**
+ * Constructor
+ */
+ Location();
+
+ /**
+ * Destructor
+ */
+ virtual ~Location() {}
+
+ /**
+ * Draw the view contents
+ */
+ void draw() override;
+
+ /**
+ * Keypress handler
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index a302fd368c2..e3c185fe63a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -47,6 +47,7 @@ MODULE_OBJS := \
mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
mm1/views/spells/fly.o \
+ mm1/views/spells/location.o \
mm1/views/spells/teleport.o \
mm1/views/are_you_ready.o \
mm1/views/character_base.o \
Commit: 58535f33d9ceb9c8b4336b869ba44133d3f2bddd
https://github.com/scummvm/scummvm/commit/58535f33d9ceb9c8b4336b869ba44133d3f2bddd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: Implemented Detect Magic spell and view
Changed paths:
A engines/mm/mm1/views/spells/detect_magic.cpp
A engines/mm/mm1/views/spells/detect_magic.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index d569a21a52e..f77eb17a6c6 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -252,10 +252,9 @@
not_enough_sp: "*** NOT ENOUGH SPELL POINTS ***"
full: "*** BACKPACK FULL ***"
spells:
+ detect_charges: "MAGIC (CHARGES)"
fly_to_x: "FLY TO (A-E): "
fly_to_y: "(1-4): "
- teleport_dir: "DIRECTION (N,E,S,W): "
- teleport_squares: "# OF SQUARES (0-9): "
location_loc: "LOCATION: "
location_town: "IN TOWN"
location_castle: "IN CASTLE"
@@ -266,6 +265,8 @@
location_surface_x: "SURFACE: X="
location_inside_x: "INSIDE: X="
location_facing: "FACING: "
+ teleport_dir: "DIRECTION (N,E,S,W): "
+ teleport_squares: "# OF SQUARES (0-9): "
enhdialogs:
character:
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 7a74f0d8d46..96a02cc22ed 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -42,7 +42,7 @@ void Inventory::clear() {
void Inventory::synchronize(Common::Serializer &s, bool ids) {
for (int i = 0; i < INVENTORY_COUNT; ++i)
- s.syncAsByte(ids ? _items[i]._id : _items[i]._field14);
+ s.syncAsByte(ids ? _items[i]._id : _items[i]._charges);
}
bool Inventory::empty() const {
@@ -61,10 +61,18 @@ bool Inventory::full() const {
return true;
}
+uint Inventory::size() const {
+ for (int i = INVENTORY_COUNT - 1; i >= 0; --i) {
+ if (_items[i])
+ return i + 1;
+ }
+ return 0;
+}
+
uint Inventory::add(byte id, byte field14) {
uint idx = getFreeSlot();
_items[idx]._id = id;
- _items[idx]._field14 = field14;
+ _items[idx]._charges = field14;
return idx;
}
@@ -200,7 +208,7 @@ Character::TradeResult Character::trade(int whoTo, int itemIndex) {
Inventory::Entry e = _backpack[itemIndex];
_backpack.removeAt(itemIndex);
- dest._backpack.add(e._id, e._field14);
+ dest._backpack.add(e._id, e._charges);
return TRADE_SUCCESS;
}
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 564bce0c074..a0b06cc3db5 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -60,7 +60,7 @@ class Inventory {
public:
struct Entry {
byte _id = 0;
- byte _field14 = 0;
+ byte _charges = 0;
operator bool() const { return _id != 0; }
// bool operator!() const { return !_id; }
// operator byte() const { return _id; }
@@ -112,6 +112,11 @@ public:
*/
bool full() const;
+ /**
+ * Returns the size of the backpack that's filled in
+ */
+ uint size() const;
+
/**
* Adds an item to the inventory
*/
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 56b61412afa..cceb497d9dd 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -25,6 +25,7 @@
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
+#include "mm/mm1/views/spells/detect_magic.h"
#include "mm/mm1/views/spells/fly.h"
#include "mm/mm1/views/spells/location.h"
#include "mm/mm1/views/spells/teleport.h"
@@ -463,8 +464,8 @@ SpellResult Spells::cleric74_resurrection(Character *chr) {
}
SpellResult Spells::wizard12_detectMagic(Character *chr) {
- error("TODO: detectMagic");
- return SR_FAILED;
+ Views::Spells::DetectMagic::show();
+ return SR_SUCCESS_SILENT;
}
SpellResult Spells::wizard15_leatherSkin(Character *chr) {
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index a8db5f1af4d..3384a7631ab 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -235,7 +235,7 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
void CharacterInfo::equipItem(uint index) {
Character &c = *g_globals->_currCharacter;
uint itemId = c._backpack[index]._id;
- uint item14 = c._backpack[index]._field14;
+ uint item14 = c._backpack[index]._charges;
int classBit = 0;
Common::String equipError;
@@ -346,7 +346,7 @@ void CharacterInfo::equipItem(uint index) {
equipError = STRING["dialogs.character.not_equipped"];
_textPos.x = 10;
} else if (item._equipMode == EQUIP_CURSED) {
- c._equipped[freeIndex]._field14 += item._val10;
+ c._equipped[freeIndex]._charges += item._val10;
}
}
}
@@ -392,7 +392,7 @@ void CharacterInfo::equipItem(uint index) {
void CharacterInfo::removeItem(uint index) {
Character &c = *g_globals->_currCharacter;
uint itemId = c._equipped[index]._id;
- uint item14 = c._equipped[index]._field14;
+ uint item14 = c._equipped[index]._charges;
Common::String removeError;
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index d7cfe312d6d..709751c2182 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -44,6 +44,7 @@
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/views/spells/cast_spell.h"
+#include "mm/mm1/views/spells/detect_magic.h"
#include "mm/mm1/views/spells/fly.h"
#include "mm/mm1/views/spells/location.h"
#include "mm/mm1/views/spells/teleport.h"
@@ -75,6 +76,7 @@ private:
Views::Locations::Training _training;
Views::Spells::CastSpell _castSpell;
+ Views::Spells::DetectMagic _detectMagicSpell;
Views::Spells::Fly _flySpell;
Views::Spells::Location _locationSpell;
Views::Spells::Teleport _telportSpell;
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index fc3fa784ee4..ba55c3cbb81 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -66,7 +66,7 @@ void BlacksmithSellItem::selectItem(uint index) {
// Remove the item
int itemId = c._backpack[index]._id;
- int v14 = c._backpack[index]._field14;
+ int v14 = c._backpack[index]._charges;
c._backpack.removeAt(index);
getItem(itemId);
diff --git a/engines/mm/mm1/views/spells/detect_magic.cpp b/engines/mm/mm1/views/spells/detect_magic.cpp
new file mode 100644
index 00000000000..6dfd4fe5f56
--- /dev/null
+++ b/engines/mm/mm1/views/spells/detect_magic.cpp
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/spells/detect_magic.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+void DetectMagic::show() {
+ UIElement *view = dynamic_cast<DetectMagic *>(g_events->findView("DetectMagic"));
+ assert(view);
+
+ view->open();
+}
+
+DetectMagic::DetectMagic() : SpellView("DetectMagic") {
+ _bounds = getLineBounds(20, 24);
+}
+
+void DetectMagic::draw() {
+ clearSurface();
+ escToGoBack(0);
+
+ writeString(0, 0, STRING["dialogs.spells.detect_charges"]);
+ _textPos.x = 20;
+ _textPos.y = 0;
+
+ Inventory &inv = g_globals->_currCharacter->_backpack;
+ for (uint i = 0; i < inv.size(); ++i) {
+ writeChar('A' + i);
+ writeChar(')');
+
+ int itemId = inv[i]._id;
+ bool flag = false;
+ if (itemId < 12)
+ flag = false;
+ else if (itemId < 61)
+ flag = true;
+ else if (itemId < 66)
+ flag = false;
+ else if (itemId < 86)
+ flag = true;
+ else if (itemId < 93)
+ flag = false;
+ else if (itemId < 121)
+ flag = true;
+ else if (itemId < 128)
+ flag = false;
+ else if (itemId < 156)
+ flag = true;
+ else if (itemId < 158)
+ flag = false;
+ else if (itemId < 255)
+ flag = true;
+ else
+ flag = false;
+
+ if (flag) {
+ writeString("Y (");
+ writeNumber(inv[i]._charges);
+ writeChar(')');
+
+ } else {
+ writeChar('N');
+ }
+
+ // Move to write position for next item (if any)
+ if (_textPos.x < 30) {
+ _textPos.x = 30;
+ } else {
+ _textPos.x = 20;
+ _textPos.y++;
+ }
+ }
+}
+
+bool DetectMagic::msgKeypress(const KeypressMessage &msg) {
+ close();
+ return true;
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/spells/detect_magic.h b/engines/mm/mm1/views/spells/detect_magic.h
new file mode 100644
index 00000000000..e00a04247de
--- /dev/null
+++ b/engines/mm/mm1/views/spells/detect_magic.h
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SPELLS_DETECT_MAGIC_H
+#define MM1_VIEWS_SPELLS_DETECT_MAGIC_H
+
+#include "mm/mm1/views/spells/spell_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+class DetectMagic : public SpellView {
+public:
+ /**
+ * Show the view
+ */
+ static void show();
+public:
+ /**
+ * Constructor
+ */
+ DetectMagic();
+
+ /**
+ * Destructor
+ */
+ virtual ~DetectMagic() {}
+
+ /**
+ * Draw the view contents
+ */
+ void draw() override;
+
+ /**
+ * Keypress handler
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index e3c185fe63a..b2d91a9e645 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -46,6 +46,7 @@ MODULE_OBJS := \
mm1/views/locations/training.o \
mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
+ mm1/views/spells/detect_magic.o \
mm1/views/spells/fly.o \
mm1/views/spells/location.o \
mm1/views/spells/teleport.o \
Commit: 1fed7d35807e6a16e955a80f456350165171e527
https://github.com/scummvm/scummvm/commit/1fed7d35807e6a16e955a80f456350165171e527
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:07+01:00
Commit Message:
MM: MM1: Remaining wizard spell views
Changed paths:
A engines/mm/mm1/views/spells/duplication.cpp
A engines/mm/mm1/views/spells/duplication.h
A engines/mm/mm1/views/spells/recharge_item.cpp
A engines/mm/mm1/views/spells/recharge_item.h
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
engines/mm/mm1/views/spells/teleport.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 96a02cc22ed..956e5911bcc 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -69,10 +69,10 @@ uint Inventory::size() const {
return 0;
}
-uint Inventory::add(byte id, byte field14) {
+uint Inventory::add(byte id, byte charges) {
uint idx = getFreeSlot();
_items[idx]._id = id;
- _items[idx]._charges = field14;
+ _items[idx]._charges = charges;
return idx;
}
@@ -305,7 +305,7 @@ Character::BuyResult Character::buyItem(byte itemId) {
// Add the item
_gold -= item._cost;
- _backpack.add(itemId, item._val13);
+ _backpack.add(itemId, item._maxCharges);
return BUY_SUCCESS;
}
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index a0b06cc3db5..25740dfa9cd 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -120,7 +120,7 @@ public:
/**
* Adds an item to the inventory
*/
- uint add(byte id, byte field14);
+ uint add(byte id, byte charges);
/**
* Removes an index from the inventory
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index f185859d3c9..26a92f416b3 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -55,7 +55,7 @@ struct ItemData {
byte _val10;
byte _val11;
byte _spellId;
- byte _val13;
+ byte _maxCharges;
uint16 _cost;
byte _val16;
byte _val17;
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 709751c2182..59d7a479554 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -45,8 +45,10 @@
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/views/spells/detect_magic.h"
+#include "mm/mm1/views/spells/duplication.h"
#include "mm/mm1/views/spells/fly.h"
#include "mm/mm1/views/spells/location.h"
+#include "mm/mm1/views/spells/recharge_item.h"
#include "mm/mm1/views/spells/teleport.h"
namespace MM {
@@ -77,8 +79,10 @@ private:
Views::Spells::CastSpell _castSpell;
Views::Spells::DetectMagic _detectMagicSpell;
+ Views::Spells::Duplication _duplicationSpell;
Views::Spells::Fly _flySpell;
Views::Spells::Location _locationSpell;
+ Views::Spells::RechargeItem _rechargeItemSpell;
Views::Spells::Teleport _telportSpell;
public:
Dialogs() {}
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index ba55c3cbb81..7e41e89c80c 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -70,7 +70,7 @@ void BlacksmithSellItem::selectItem(uint index) {
c._backpack.removeAt(index);
getItem(itemId);
- if (!v14 && g_globals->_currItem._val13)
+ if (!v14 && g_globals->_currItem._maxCharges)
g_globals->_currItem._cost /= 2;
c._gold += g_globals->_currItem._cost / 2;
diff --git a/engines/mm/mm1/views/spells/duplication.cpp b/engines/mm/mm1/views/spells/duplication.cpp
new file mode 100644
index 00000000000..7a291c48c69
--- /dev/null
+++ b/engines/mm/mm1/views/spells/duplication.cpp
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/spells/duplication.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+void Duplication::show() {
+ UIElement *view = dynamic_cast<Duplication *>(g_events->findView("Duplication"));
+ assert(view);
+
+ view->open();
+}
+
+Duplication::Duplication() : SpellView("Duplication") {
+ _bounds = getLineBounds(20, 24);
+}
+
+void Duplication::draw() {
+ clearSurface();
+ escToGoBack(0);
+
+ writeString(10, 0, STRING["dialogs.charcater.which_item"]);
+}
+
+bool Duplication::msgKeypress(const KeypressMessage &msg) {
+ Inventory &inv = g_globals->_currCharacter->_backpack;
+
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ spellFailed();
+
+ } else if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode < (Common::KEYCODE_a + (int)inv.size())) {
+ int itemIndex = msg.keycode - Common::KEYCODE_a;
+
+ if (inv.full()) {
+ // No space to duplicate
+ spellFailed();
+ return true;
+ }
+
+ if (g_engine->getRandomNumber(100) == 100) {
+ // OMG: The original seriously had this fringe
+ // case that happens so rarely
+ inv.removeAt(itemIndex); // Break item
+ spellFailed();
+ } else if (inv[itemIndex]._id >= 230) {
+ spellFailed();
+ } else {
+ // Add a copy of the item
+ inv.add(inv[itemIndex]._id,
+ inv[itemIndex]._charges);
+ }
+ }
+
+ return true;
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/spells/duplication.h b/engines/mm/mm1/views/spells/duplication.h
new file mode 100644
index 00000000000..72035b665cb
--- /dev/null
+++ b/engines/mm/mm1/views/spells/duplication.h
@@ -0,0 +1,77 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SPELLS_DUPLICATION_H
+#define MM1_VIEWS_SPELLS_DUPLICATION_H
+
+#include "mm/mm1/views/spells/spell_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+class Duplication : public SpellView {
+private:
+ enum Mode {
+ SELECT_ITEM, CAST
+ };
+ Mode _mode = SELECT_ITEM;
+ char _direction = '\0';
+ int _squares = 0;
+
+ /**
+ * Handle the Duplicationing
+ */
+ void duplicate();
+public:
+ /**
+ * Show the view
+ */
+ static void show();
+public:
+ /**
+ * Constructor
+ */
+ Duplication();
+
+ /**
+ * Destructor
+ */
+ virtual ~Duplication() {}
+
+ /**
+ * Draw the view contents
+ */
+ void draw() override;
+
+ /**
+ * Keypress handler
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/spells/recharge_item.cpp b/engines/mm/mm1/views/spells/recharge_item.cpp
new file mode 100644
index 00000000000..4b810f15e40
--- /dev/null
+++ b/engines/mm/mm1/views/spells/recharge_item.cpp
@@ -0,0 +1,79 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/spells/recharge_item.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+void RechargeItem::show() {
+ UIElement *view = dynamic_cast<RechargeItem *>(g_events->findView("RechargeItem"));
+ assert(view);
+
+ view->open();
+}
+
+RechargeItem::RechargeItem() : SpellView("RechargeItem") {
+ _bounds = getLineBounds(20, 24);
+}
+
+void RechargeItem::draw() {
+ clearSurface();
+ escToGoBack(0);
+
+ writeString(10, 0, STRING["dialogs.charcater.which_item"]);
+}
+
+bool RechargeItem::msgKeypress(const KeypressMessage &msg) {
+ Inventory &inv = g_globals->_currCharacter->_backpack;
+
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ spellFailed();
+
+ } else if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode < (Common::KEYCODE_a + inv.size())) {
+ int itemIndex = msg.keycode - Common::KEYCODE_a;
+ Item *item = getItem(inv[itemIndex]._id);
+
+ if (g_engine->getRandomNumber(100) == 100) {
+ // OMG: The original seriously had this fringe
+ // case that happens so rarely
+ inv.removeAt(itemIndex); // Break item
+ spellFailed();
+ } else {
+ inv[itemIndex]._charges = MIN(
+ inv[itemIndex]._charges +
+ g_engine->getRandomNumber(4),
+ (int)item->_maxCharges);
+ }
+ }
+
+ return true;
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/spells/recharge_item.h b/engines/mm/mm1/views/spells/recharge_item.h
new file mode 100644
index 00000000000..3f08909e1d8
--- /dev/null
+++ b/engines/mm/mm1/views/spells/recharge_item.h
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_SPELLS_RECHARGE_ITEM_H
+#define MM1_VIEWS_SPELLS_RECHARGE_ITEM_H
+
+#include "mm/mm1/views/spells/spell_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Spells {
+
+class RechargeItem : public SpellView {
+public:
+ /**
+ * Show the view
+ */
+ static void show();
+public:
+ /**
+ * Constructor
+ */
+ RechargeItem();
+
+ /**
+ * Destructor
+ */
+ virtual ~RechargeItem() {}
+
+ /**
+ * Draw the view contents
+ */
+ void draw() override;
+
+ /**
+ * Keypress handler
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/spells/teleport.cpp b/engines/mm/mm1/views/spells/teleport.cpp
index 7ca43a2abd4..10f47398e01 100644
--- a/engines/mm/mm1/views/spells/teleport.cpp
+++ b/engines/mm/mm1/views/spells/teleport.cpp
@@ -49,9 +49,6 @@ void Teleport::draw() {
clearSurface();
escToGoBack(0);
- clearSurface();
- escToGoBack(0);
-
writeString(10, 1, STRING["dialogs.spells.teleport_dir"]);
writeChar((_mode == SELECT_DIRECTION) ? '_' : _direction);
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b2d91a9e645..89d2263264f 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -47,8 +47,10 @@ MODULE_OBJS := \
mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
mm1/views/spells/detect_magic.o \
+ mm1/views/spells/duplication.o \
mm1/views/spells/fly.o \
mm1/views/spells/location.o \
+ mm1/views/spells/recharge_item.o \
mm1/views/spells/teleport.o \
mm1/views/are_you_ready.o \
mm1/views/character_base.o \
Commit: 1b553ba1ab04dfb71a128f153774ef54cc138c94
https://github.com/scummvm/scummvm/commit/1b553ba1ab04dfb71a128f153774ef54cc138c94
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Beginnings of encounter logic
Changed paths:
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/game/rest.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views/spells/recharge_item.cpp
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index fbf2cac85e7..de6379048a7 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -19,17 +19,79 @@
*
*/
-#include "mm/mm1/events.h"
#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
namespace Game {
void Encounter::execute() {
+ Maps::Map &map = *g_maps->_currentMap;
+ int comp, maxRand, maxVal;
+ _val1 = _val2 = _val3 = 0;
+
+ if (!_flag) {
+ _levelIndex = _val5 = 0;
+ }
+
+ _totalLevels = _highestLevel = 0;
+ _val6 = _val8 = _val9 = _val10 = 0;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ const Character &c = g_globals->_party[i];
+ _highestLevel = MAX(_highestLevel, (int)c._level._current);
+
+ if (!(c._condition & (BAD_CONDITION | PARALYZED | UNCONSCIOUS)))
+ _totalLevels = MIN(_totalLevels + c._level._current, 255);
+ }
+
+ _totalLevels /= 2;
+ _highestLevel /= 2;
+
+ bool firstLoop = !_flag;
+ _flag = false;
+
+ while (firstLoop || _levelIndex < _totalLevels) {
+ randomAdjust();
+ maxRand = _val6 + _highestLevel;
+ if (maxRand >= 2) {
+ int highestRand = map[33];
+ maxRand = MIN(maxRand, highestRand);
+ comp = g_engine->getRandomNumber(maxRand);
+ } else {
+ comp = 1;
+ }
+
+ maxVal = map[47];
+ if (comp < maxVal) {
+ comp = MIN(maxVal, 10);
+ }
+
+ // TODO
+ }
+
// TODO: Handle properly
}
+void Encounter::randomAdjust() {
+ int rval = g_engine->getRandomNumber(100);
+ _val6 = 0;
+
+ if (rval < 51) {
+ } else if (rval < 71)
+ _val6 += 1;
+ else if (rval < 86)
+ _val6 += 2;
+ else if (rval < 96)
+ _val6 += 3;
+ else
+ _val6 += 4;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index c33ebfb397e..432ce623d1d 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -27,7 +27,16 @@ namespace MM1 {
namespace Game {
struct Encounter {
- static void execute();
+private:
+ bool _flag = false;
+ int _val1 = 0, _val2 = 0, _val3 = 0;
+ int _levelIndex = 0, _val5 = 0, _val6 = 0;
+ int _val8 = 0, _val9 = 0, _val10 = 0;
+ int _totalLevels = 0, _highestLevel = 0;
+
+ void randomAdjust();
+public:
+ void execute();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/rest.cpp b/engines/mm/mm1/game/rest.cpp
index 065bf62753a..4336987a116 100644
--- a/engines/mm/mm1/game/rest.cpp
+++ b/engines/mm/mm1/game/rest.cpp
@@ -47,7 +47,7 @@ void Rest::check() {
}
// Start an encounter
- Game::Encounter::execute();
+ g_globals->_encounters.execute();
}
}
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index b3d6ece1a51..3f324f3d394 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -30,6 +30,7 @@
#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/items.h"
#include "mm/mm1/data/roster.h"
+#include "mm/mm1/game/encounter.h"
#include "mm/mm1/maps/maps.h"
namespace MM {
@@ -46,6 +47,7 @@ public:
bool _intangible = false; // Console flag
BitmapFont _font;
bool _heardRumor = false;
+ Game::Encounter _encounters;
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
diff --git a/engines/mm/mm1/views/spells/recharge_item.cpp b/engines/mm/mm1/views/spells/recharge_item.cpp
index 4b810f15e40..d9d1fce90bb 100644
--- a/engines/mm/mm1/views/spells/recharge_item.cpp
+++ b/engines/mm/mm1/views/spells/recharge_item.cpp
@@ -53,7 +53,7 @@ bool RechargeItem::msgKeypress(const KeypressMessage &msg) {
spellFailed();
} else if (msg.keycode >= Common::KEYCODE_a &&
- msg.keycode < (Common::KEYCODE_a + inv.size())) {
+ msg.keycode < (Common::KEYCODE_a + (int)inv.size())) {
int itemIndex = msg.keycode - Common::KEYCODE_a;
Item *item = getItem(inv[itemIndex]._id);
Commit: 80feff139b1b6cac1a9567e860bd6ebe79ccb210
https://github.com/scummvm/scummvm/commit/80feff139b1b6cac1a9567e860bd6ebe79ccb210
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Adding more encounter setup
Changed paths:
A engines/mm/mm1/data/monsters.cpp
A engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
new file mode 100644
index 00000000000..76fba73e3b4
--- /dev/null
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -0,0 +1,32 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/monsters.h"
+
+namespace MM {
+namespace MM1 {
+
+const Monster MONSTERS[1] = {
+ { "FLESH EATER ", 6, 0, 2, 2, 6, 1, 7, 40, 0, 0, 0, 0, 0x82, 0 }
+};
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
new file mode 100644
index 00000000000..612aa5c6273
--- /dev/null
+++ b/engines/mm/mm1/data/monsters.h
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_MONSTERS_H
+#define MM1_DATA_MONSTERS_H
+
+#include "common/scummsys.h"
+
+namespace MM {
+namespace MM1 {
+
+struct Monster {
+ const char *_name; // char _name[15];
+ byte _attr[17];
+};
+
+extern const Monster MONSTERS[1];
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index de6379048a7..1eeb92dc4b4 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/data/monsters.h"
#include "mm/mm1/maps/maps.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
@@ -71,6 +72,27 @@ void Encounter::execute() {
comp = MIN(maxVal, 10);
}
+ assert(_val5 < 15);
+ _arr1[_val5] = comp;
+ _val11 = comp;
+ _levelIndex += comp;
+
+ _randVal = g_engine->getRandomNumber(16);
+ _arr2[_val5] = _randVal;
+ _val5 = (_val5 + 1) & 0xff;
+
+ if (_val5 < 15) {
+ if (_val5 < map[34]) {
+ getMonsterVal();
+
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+
+
// TODO
}
@@ -92,6 +114,11 @@ void Encounter::randomAdjust() {
_val6 += 4;
}
+void Encounter::getMonsterVal() {
+ assert(_val11 >= 8);
+ _monsterValP = &MONSTERS[_randVal]._attr[(_val11 - 8) * 2];
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 432ce623d1d..c7609483feb 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -22,6 +22,8 @@
#ifndef MM1_GAME_ENCOUNTER_H
#define MM1_GAME_ENCOUNTER_H
+#include "common/scummsys.h"
+
namespace MM {
namespace MM1 {
namespace Game {
@@ -32,9 +34,14 @@ private:
int _val1 = 0, _val2 = 0, _val3 = 0;
int _levelIndex = 0, _val5 = 0, _val6 = 0;
int _val8 = 0, _val9 = 0, _val10 = 0;
+ int _val11 = 0;
int _totalLevels = 0, _highestLevel = 0;
+ int _randVal = 0;
+ byte _arr1[15], _arr2[15];
+ const byte *_monsterValP;
void randomAdjust();
+ void getMonsterVal();
public:
void execute();
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 89d2263264f..297d9a299a3 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -18,6 +18,7 @@ MODULE_OBJS := \
mm1/data/game_state.o \
mm1/data/items.o \
mm1/data/locations.o \
+ mm1/data/monsters.o \
mm1/data/party.o \
mm1/data/roster.o \
mm1/data/spells.o \
Commit: e907ce5e06e9e75e814f0ac6b8e49480ff056c43
https://github.com/scummvm/scummvm/commit/e907ce5e06e9e75e814f0ac6b8e49480ff056c43
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Remainder of encounter setup
Changed paths:
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map00.cpp
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 1eeb92dc4b4..f1d46f01cc9 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -82,21 +82,30 @@ void Encounter::execute() {
_val5 = (_val5 + 1) & 0xff;
if (_val5 < 15) {
- if (_val5 < map[34]) {
- getMonsterVal();
-
- } else {
- break;
+ if (_val5 >= map[34])
+ goto exit_loop;
+
+ getMonsterVal();
+ maxVal = g_engine->getRandomNumber(*_monsterValP);
+ for (int i = 0; i < maxVal; ++i) {
+ assert(_val5 > 0);
+ _arr1[_val5] = _arr1[_val5 - 1];
+ _levelIndex += _arr1[_val5];
+ _arr2[_val5] = _arr2[_val5 - 1];
+
+ if (++_val5 >= 15)
+ goto exit_loop;
+
+ if (_val5 >= map[34])
+ goto exit_loop;
}
} else {
- break;
+ goto exit_loop;
}
-
-
- // TODO
}
- // TODO: Handle properly
+exit_loop:
+ g_events->addView("Encounter");
}
void Encounter::randomAdjust() {
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 594d3c10165..99be8ee74f3 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -65,7 +65,7 @@ darkness:
} else if (_stepRandom) {
_encounterFlag = true;
_stepRandom = false;
- addView("Encounter");
+ g_globals->_encounters.execute();
} else {
map.checkPartyDead();
}
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 3700ee14faa..abfeedf40a3 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -54,7 +54,7 @@ void Map00::special() {
// All other cells on the map are encounters
g_maps->clearSpecial();
- g_events->addView("Encounter");
+ g_globals->_encounters.execute();
}
void Map00::special00() {
Commit: a6562e60e16a48f91b84e1e783b804e5edcd99c7
https://github.com/scummvm/scummvm/commit/a6562e60e16a48f91b84e1e783b804e5edcd99c7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Beginnings of Encounter view
Changed paths:
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 612aa5c6273..cadd187915d 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -29,7 +29,8 @@ namespace MM1 {
struct Monster {
const char *_name; // char _name[15];
- byte _attr[17];
+ byte _unused;
+ byte _attr[16];
};
extern const Monster MONSTERS[1];
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index f1d46f01cc9..e8016770efb 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -105,6 +105,28 @@ void Encounter::execute() {
}
exit_loop:
+ _monsterList.clear();
+
+ for (int i = 0; i < _val5; ++i) {
+ maxVal = (_arr1[i] - 1) * 16 + _arr2[i];
+ if ((_arr1[i] > 0 && _arr1[i] <= 12) || (maxVal >= 196)) {
+ _arr1[i] = 10;
+ _arr2[i] = g_engine->getRandomNumber(15);
+ }
+
+ // Add monster details to list
+ _val11 = _arr1[i];
+ assert(_val11 == 1);
+ const Monster &mons = MONSTERS[_arr2[i]];
+ _monsterList.push_back(mons);
+
+ if (_val11 > _val9) {
+ _val9 = _val11;
+ _val10 = mons._attr[0];
+ _val8 = mons._attr[15];
+ }
+ }
+
g_events->addView("Encounter");
}
@@ -124,8 +146,9 @@ void Encounter::randomAdjust() {
}
void Encounter::getMonsterVal() {
- assert(_val11 >= 8);
- _monsterValP = &MONSTERS[_randVal]._attr[(_val11 - 8) * 2];
+ _randVal = 0; //****DEBUG****
+ assert(_val11 >= 9);
+ _monsterValP = &MONSTERS[_randVal]._attr[(_val11 - 9) * 2];
}
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index c7609483feb..1d9d3d2a216 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -22,7 +22,8 @@
#ifndef MM1_GAME_ENCOUNTER_H
#define MM1_GAME_ENCOUNTER_H
-#include "common/scummsys.h"
+#include "common/array.h"
+#include "mm/mm1/data/monsters.h"
namespace MM {
namespace MM1 {
@@ -33,7 +34,7 @@ private:
bool _flag = false;
int _val1 = 0, _val2 = 0, _val3 = 0;
int _levelIndex = 0, _val5 = 0, _val6 = 0;
- int _val8 = 0, _val9 = 0, _val10 = 0;
+ int _val9 = 0, _val10 = 0;
int _val11 = 0;
int _totalLevels = 0, _highestLevel = 0;
int _randVal = 0;
@@ -42,6 +43,9 @@ private:
void randomAdjust();
void getMonsterVal();
+public:
+ Common::Array<Monster> _monsterList;
+ int _val8 = 0;
public:
void execute();
};
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index bdf05c07a3d..335753cd49b 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -30,8 +30,23 @@ Encounter::Encounter() : TextView("Encounter") {
}
void Encounter::draw() {
- clearSurface();
- writeString(10, 10, "Encounter");
+ const Game::Encounter &enc = g_globals->_encounters;
+
+ // Clear the commands area
+ Graphics::ManagedSurface s = getSurface();
+ s.fillRect(Common::Rect(31 * 8, 0, 320, 17 * 8), 0);
+
+ // Write the monster list
+ for (uint i = 0; i < enc._monsterList.size(); ++i) {
+ writeChar(22, i, 'A' + i);
+ writeString(") ");
+ writeString(enc._monsterList[i]._name);
+ }
+
+ // Display the monster
+
+ // Write the encounter options
+
}
} // namespace Views
Commit: 84f7c31ef5f55830ca9c7583fa2174e5b096001b
https://github.com/scummvm/scummvm/commit/84f7c31ef5f55830ca9c7583fa2174e5b096001b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Added encounter console command
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/views/dialogs.h
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 3f0cbc09d8c..c2604f04cd6 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -37,6 +37,7 @@ Console::Console() : GUI::Debugger() {
registerCmd("pos", WRAP_METHOD(Console, cmdPos));
registerCmd("intangible", WRAP_METHOD(Console, cmdIntangible));
registerCmd("cast", WRAP_METHOD(Console, cmdCast));
+ registerCmd("encounter", WRAP_METHOD(Console, cmdEncounter));
}
bool Console::cmdDumpMap(int argc, const char **argv) {
@@ -232,5 +233,10 @@ bool Console::cmdCast(int argc, const char **argv) {
}
}
+bool Console::cmdEncounter(int argc, const char **argv) {
+ g_globals->_encounters.execute();
+ return false;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index 2654f883b46..7dca6197d93 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -60,6 +60,11 @@ protected:
*/
bool cmdCast(int argc, const char **argv);
+ /**
+ * Trigger an encounter
+ */
+ bool cmdEncounter(int argc, const char **argv);
+
public:
Console();
~Console() override {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 59d7a479554..2ee43d9ec77 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -34,7 +34,6 @@
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/characters.h"
-#include "mm/mm1/views/encounter.h"
#include "mm/mm1/views/rest.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
Commit: 765a330f2b25f081f0f745c2dc28b7f21ad9e319
https://github.com/scummvm/scummvm/commit/765a330f2b25f081f0f745c2dc28b7f21ad9e319
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Some fixes to encounter setup
Changed paths:
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index cadd187915d..49acc4f5176 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -29,7 +29,7 @@ namespace MM1 {
struct Monster {
const char *_name; // char _name[15];
- byte _unused;
+ byte _count;
byte _attr[16];
};
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index e8016770efb..159423a3ad4 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -33,6 +33,7 @@ namespace Game {
void Encounter::execute() {
Maps::Map &map = *g_maps->_currentMap;
int comp, maxRand, maxVal;
+ const Monster *monsterP;
_val1 = _val2 = _val3 = 0;
if (!_flag) {
@@ -85,8 +86,10 @@ void Encounter::execute() {
if (_val5 >= map[34])
goto exit_loop;
- getMonsterVal();
- maxVal = g_engine->getRandomNumber(*_monsterValP);
+ assert(_val11 == 1);
+ monsterP = getMonster();
+ maxVal = g_engine->getRandomNumber(monsterP->_count);
+
for (int i = 0; i < maxVal; ++i) {
assert(_val5 > 0);
_arr1[_val5] = _arr1[_val5 - 1];
@@ -145,10 +148,16 @@ void Encounter::randomAdjust() {
_val6 += 4;
}
+const Monster *Encounter::getMonster() {
+ _randVal = 1; //****DEBUG****
+ assert(_randVal > 0);
+ return &MONSTERS[_randVal - 1];
+}
+
void Encounter::getMonsterVal() {
- _randVal = 0; //****DEBUG****
- assert(_val11 >= 9);
- _monsterValP = &MONSTERS[_randVal]._attr[(_val11 - 9) * 2];
+ _randVal = 1; //****DEBUG****
+ assert(_val11 >= 8 && _randVal > 0);
+ _monsterValP = &MONSTERS[_randVal - 1]._attr[(_val11 - 8) * 2];
}
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 1d9d3d2a216..1e880921242 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -42,6 +42,7 @@ private:
const byte *_monsterValP;
void randomAdjust();
+ const Monster *getMonster();
void getMonsterVal();
public:
Common::Array<Monster> _monsterList;
Commit: 443dfb2eed24011e65ac984c19221621d64a33cf
https://github.com/scummvm/scummvm/commit/443dfb2eed24011e65ac984c19221621d64a33cf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Further encounter setup fixes
Changed paths:
engines/mm/mm1/game/encounter.cpp
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 159423a3ad4..6a8e985133b 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -59,6 +59,7 @@ void Encounter::execute() {
while (firstLoop || _levelIndex < _totalLevels) {
randomAdjust();
+
maxRand = _val6 + _highestLevel;
if (maxRand >= 2) {
int highestRand = map[33];
@@ -112,7 +113,10 @@ exit_loop:
for (int i = 0; i < _val5; ++i) {
maxVal = (_arr1[i] - 1) * 16 + _arr2[i];
- if ((_arr1[i] > 0 && _arr1[i] <= 12) || (maxVal >= 196)) {
+ if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
+ // TODO: This section doesn't make sense, since it will
+ // result in an invalid monster offset calculated
+ warning("TODO: Nonsensical monster offset set");
_arr1[i] = 10;
_arr2[i] = g_engine->getRandomNumber(15);
}
@@ -149,14 +153,12 @@ void Encounter::randomAdjust() {
}
const Monster *Encounter::getMonster() {
- _randVal = 1; //****DEBUG****
assert(_randVal > 0);
return &MONSTERS[_randVal - 1];
}
void Encounter::getMonsterVal() {
- _randVal = 1; //****DEBUG****
- assert(_val11 >= 8 && _randVal > 0);
+ assert(_val11 == 1 && _randVal > 0);
_monsterValP = &MONSTERS[_randVal - 1]._attr[(_val11 - 8) * 2];
}
Commit: 9c44cb4f0b410f71ff46fffad800785663af3f0e
https://github.com/scummvm/scummvm/commit/9c44cb4f0b410f71ff46fffad800785663af3f0e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:08+01:00
Commit Message:
MM: MM1: Extract the monster list into a resource file
Changed paths:
A devtools/create_mm/files/mm1/monsters.txt
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
diff --git a/devtools/create_mm/files/mm1/monsters.txt b/devtools/create_mm/files/mm1/monsters.txt
new file mode 100644
index 00000000000..c3dbbd092c7
--- /dev/null
+++ b/devtools/create_mm/files/mm1/monsters.txt
@@ -0,0 +1,195 @@
+"FLESH EATER ", 6, 0, 2, 2, 6, 1, 7, 50, 0, 0, 0, 0, 130, 0, 0, 16, 4
+"BATTLE RAT ", 10, 1, 1, 3, 3, 1, 12, 50, 0, 2, 0, 0, 130, 0, 0, 0, 6
+"SLITHER BEAST ", 6, 0, 2, 4, 8, 1, 10, 125, 0, 0, 0, 0, 0, 0, 0, 0, 35
+"GNOME ", 6, 50, 3, 5, 6, 1, 12, 125, 0, 2, 20, 1, 0, 132, 0, 6, 8
+"GOBLIN ", 12, 0, 1, 4, 6, 1, 10, 50, 0, 2, 0, 0, 0, 131, 0, 4, 15
+"GREMLIN ", 6, 1, 1, 3, 3, 2, 4, 125, 0, 10, 0, 4, 129, 0, 0, 0, 10
+"GUARDSMAN ", 6, 10, 0, 2, 6, 1, 14, 75, 0, 2, 0, 0, 0, 134, 0, 150, 55
+"KOBOLD ", 10, 1, 1, 4, 4, 1, 6, 50, 0, 2, 0, 0, 0, 131, 0, 4, 5
+"MUTANT LARVA ", 6, 0, 0, 0, 3, 1, 2, 50, 0, 0, 0, 7, 130, 0, 0, 0, 20
+"ORC ", 12, 5, 2, 4, 6, 1, 11, 75, 0, 10, 0, 0, 0, 134, 0, 22, 14
+"POLTERGEIST ", 6, 0, 1, 0, 2, 2, 16, 150, 0, 0, 128, 7, 131, 0, 0, 160, 60
+"RABID JACKAL ", 6, 0, 0, 3, 2, 1, 15, 50, 0, 0, 0, 0, 130, 0, 0, 16, 29
+"SKELETON ", 12, 0, 1, 3, 6, 1, 9, 50, 0, 2, 128, 7, 0, 0, 0, 160, 63
+"SNAKE ", 6, 0, 0, 2, 3, 1, 17, 125, 0, 0, 0, 0, 132, 0, 0, 16, 35
+"SPRITE ", 8, 60, 0, 10, 2, 1, 20, 250, 0, 11, 30, 1, 133, 1, 50, 8, 9
+"VAMPIRE BAT ", 8, 0, 0, 2, 3, 1, 14, 125, 0, 0, 0, 0, 134, 0, 0, 16, 24
+"MINOR DEMON ", 10, 0, 10, 5, 8, 2, 16, 200, 0, 5, 20, 15, 135, 2, 25, 218, 11
+"DEMON DOG ", 10, 3, 8, 3, 10, 2, 14, 100, 0, 0, 0, 0, 0, 0, 0, 16, 32
+"DUNG BEETLE ", 6, 1, 8, 6, 8, 1, 8, 100, 0, 8, 0, 1, 130, 0, 0, 16, 1
+"FIRE ANT ", 15, 0, 5, 5, 6, 1, 7, 100, 0, 26, 0, 67, 0, 3, 10, 20, 0
+"GHOUL ", 6, 0, 8, 4, 5, 3, 13, 200, 0, 5, 128, 7, 136, 0, 0, 16, 58
+"GNOLL ", 10, 0, 8, 5, 8, 1, 10, 100, 0, 10, 0, 0, 0, 134, 0, 6, 15
+"HAG ", 2, 0, 3, 1, 4, 2, 8, 100, 0, 1, 0, 0, 138, 4, 20, 20, 12
+"LOCUST PLAGUE ", 4, 0, 8, 5, 1, 10, 17, 200, 0, 0, 0, 7, 130, 32, 10, 47, 2
+"ORC LEADER ", 1, 0, 10, 5, 8, 1, 14, 100, 0, 28, 0, 0, 0, 138, 0, 38, 14
+"RABID LEPER ", 4, 0, 5, 0, 3, 1, 11, 100, 0, 0, 0, 0, 137, 0, 0, 16, 65
+"ROTTING CORPSE ", 6, 0, 8, 2, 4, 2, 3, 100, 0, 0, 128, 7, 137, 0, 0, 16, 65
+"SAVAGE SHREW ", 4, 5, 4, 3, 5, 3, 13, 150, 0, 0, 0, 0, 0, 0, 0, 0, 32
+"STRANGLING VINE", 10, 0, 1, 3, 3, 4, 6, 100, 0, 40, 0, 3, 134, 0, 0, 51, 47
+"THIEF ", 8, 0, 6, 3, 8, 1, 16, 100, 0, 20, 0, 0, 139, 134, 0, 4, 49
+"TROGLODYTE ", 6, 1, 8, 5, 4, 3, 11, 100, 0, 10, 0, 3, 132, 5, 20, 22, 37
+"ZOMBIE ", 8, 0, 8, 2, 8, 1, 2, 100, 0, 0, 128, 7, 130, 0, 0, 32, 7
+"ACIDIC BLOB ", 6, 0, 8, 1, 8, 2, 8, 44, 1, 0, 0, 127, 140, 6, 20, 118, 20
+"CENTAUR ", 12, 60, 20, 4, 4, 4, 12, 200, 0, 27, 0, 3, 0, 7, 20, 20, 18
+"CLERIC ", 4, 10, 15, 5, 8, 1, 12, 44, 1, 11, 0, 0, 0, 8, 50, 20, 53
+"MINOR DEVIL ", 10, 0, 15, 4, 4, 2, 15, 250, 0, 61, 20, 15, 136, 2, 30, 234, 11
+"FIRE BEETLE ", 5, 0, 16, 7, 15, 1, 6, 200, 0, 2, 0, 65, 0, 3, 30, 22, 1
+"GARGOYLE ", 6, 0, 24, 5, 4, 4, 12, 44, 1, 3, 20, 15, 136, 0, 0, 16, 11
+"GARGANTUAN ANT ", 6, 0, 18, 8, 12, 1, 9, 200, 0, 24, 0, 3, 0, 0, 0, 160, 0
+"DINOLIZARD ", 6, 0, 16, 5, 10, 1, 11, 200, 0, 0, 0, 3, 0, 0, 0, 16, 36
+"GIANT SPIDER ", 6, 1, 20, 5, 8, 1, 18, 200, 0, 1, 0, 1, 140, 0, 0, 16, 0
+"HARPY ", 6, 0, 15, 3, 5, 3, 15, 200, 0, 28, 0, 3, 0, 8, 10, 20, 25
+"HIPPOGRIFF ", 6, 5, 18, 5, 8, 3, 14, 200, 0, 12, 0, 0, 138, 0, 0, 16, 39
+"KILLER BEES ", 4, 0, 10, 10, 2, 10, 16, 44, 1, 0, 0, 7, 132, 32, 20, 42, 2
+"PEGASUS ", 6, 90, 25, 4, 8, 3, 20, 250, 0, 27, 10, 15, 135, 9, 10, 4, 38
+"SHADOW BEAST ", 6, 0, 20, 3, 5, 1, 18, 200, 0, 0, 0, 15, 141, 0, 0, 32, 60
+"WILD BOAR ", 6, 5, 15, 3, 12, 1, 14, 200, 0, 0, 0, 0, 0, 0, 0, 16, 32
+"WOLVERINE ", 3, 0, 10, 5, 5, 3, 12, 250, 0, 10, 0, 1, 0, 0, 0, 16, 29
+"BARBARIAN ", 10, 5, 50, 8, 12, 2, 15, 144, 1, 12, 20, 1, 0, 140, 0, 170, 23
+"CARYATID GUARD ", 6, 2, 20, 5, 10, 1, 15, 144, 1, 1, 25, 255, 142, 9, 10, 54, 64
+"COCKATRICE ", 6, 3, 28, 4, 8, 1, 8, 244, 1, 0, 0, 3, 143, 0, 0, 16, 28
+"CYCLOPS ", 8, 1, 32, 6, 15, 2, 10, 144, 1, 28, 0, 1, 0, 148, 0, 168, 22
+"DRUID ", 4, 2, 24, 4, 8, 2, 14, 144, 1, 3, 0, 1, 138, 7, 50, 22, 53
+"RHINO BEETLE ", 4, 0, 25, 7, 20, 1, 7, 244, 1, 24, 0, 3, 0, 6, 30, 35, 3
+"GIANT CENTIPEDE", 4, 0, 15, 5, 4, 8, 9, 244, 1, 2, 0, 3, 136, 0, 0, 32, 1
+"MAGICIAN ", 3, 1, 25, 5, 8, 1, 15, 88, 2, 29, 0, 1, 0, 10, 90, 24, 52
+"MILITIAMAN ", 6, 10, 30, 9, 10, 2, 9, 44, 1, 2, 0, 1, 0, 138, 0, 150, 50
+"ORC CHIEFTAIN ", 1, 0, 60, 10, 12, 2, 15, 244, 1, 28, 0, 1, 136, 140, 0, 170, 14
+"OGRE ", 6, 0, 45, 7, 10, 2, 12, 94, 1, 12, 0, 1, 0, 140, 0, 170, 19
+"SATYR ", 5, 50, 28, 5, 8, 2, 10, 44, 1, 26, 0, 15, 135, 8, 40, 24, 18
+"SWARMING WASPS ", 4, 0, 20, 4, 2, 10, 17, 144, 1, 0, 0, 7, 132, 32, 25, 47, 2
+"UNICORN ", 4, 90, 35, 8, 10, 3, 22, 244, 1, 7, 20, 127, 141, 9, 20, 69, 38
+"WEREWOLF ", 4, 10, 30, 7, 8, 2, 14, 144, 1, 0, 0, 7, 137, 0, 0, 144, 30
+"WIGHT ", 6, 0, 20, 6, 10, 1, 12, 244, 1, 0, 128, 7, 142, 0, 0, 160, 60
+"BARBARIAN CHIEF", 1, 0, 80, 10, 12, 3, 18, 32, 3, 28, 0, 3, 0, 143, 0, 184, 23
+"BASILISK ", 4, 2, 30, 5, 15, 1, 14, 232, 3, 0, 0, 3, 143, 11, 30, 163, 45
+"CELESTIAL STAG ", 2, 1, 50, 14, 10, 3, 19, 188, 2, 34, 0, 3, 0, 0, 0, 32, 39
+"DUST DEMON ", 3, 0, 30, 9, 12, 3, 15, 88, 2, 1, 0, 15, 7, 7, 20, 154, 34
+"GIANT SCORPION ", 4, 0, 30, 7, 8, 3, 13, 88, 2, 0, 0, 3, 12, 0, 0, 32, 0
+"5 HEADED HYDRA ", 1, 0, 80, 7, 8, 5, 12, 220, 5, 60, 0, 3, 0, 14, 40, 160, 44
+"WARRIOR CAT ", 4, 5, 40, 6, 6, 4, 17, 88, 2, 0, 0, 3, 0, 0, 0, 16, 33
+"MINOTAUR ", 2, 0, 55, 7, 35, 1, 15, 220, 5, 60, 20, 143, 144, 0, 0, 240, 40
+"OGRE CHIEF ", 1, 0, 64, 9, 15, 2, 15, 238, 2, 28, 0, 131, 0, 148, 0, 160, 19
+"PANTHRO MIST ", 6, 5, 40, 7, 8, 4, 18, 88, 2, 0, 0, 3, 0, 0, 0, 16, 33
+"PHANTOM ", 6, 0, 35, 7, 8, 2, 10, 88, 2, 0, 0, 3, 145, 0, 0, 16, 63
+"SWORDSMAN ", 6, 5, 40, 6, 10, 2, 18, 88, 2, 20, 0, 3, 0, 143, 0, 166, 55
+"TROLL ", 6, 0, 40, 6, 9, 3, 12, 88, 2, 12, 0, 131, 0, 0, 0, 224, 17
+"WOOD GOLEM ", 3, 0, 30, 5, 15, 2, 5, 32, 3, 1, 0, 191, 0, 0, 0, 176, 16
+"WRAITH ", 6, 0, 35, 6, 6, 2, 9, 32, 3, 0, 0, 135, 14, 0, 0, 176, 60
+"YETI ", 6, 5, 50, 4, 10, 2, 13, 88, 2, 10, 0, 3, 0, 148, 0, 24, 31
+"DEADLY SPORES ", 15, 0, 10, 2, 1, 1, 10, 88, 2, 0, 0, 3, 4, 12, 90, 54, 48
+"ENCHANTRESS ", 2, 1, 30, 6, 6, 2, 15, 232, 3, 37, 0, 3, 136, 13, 80, 26, 54
+"FIRE LIZARD ", 4, 1, 40, 7, 10, 3, 12, 32, 3, 0, 0, 67, 0, 3, 20, 166, 36
+"GIANT SLOTH ", 3, 70, 40, 5, 8, 4, 14, 238, 2, 8, 0, 19, 0, 0, 0, 0, 31
+"GRIFFIN ", 8, 10, 45, 7, 8, 3, 14, 188, 2, 28, 0, 3, 143, 0, 0, 16, 28
+"PYRO HYDRA ", 1, 0, 60, 7, 8, 5, 12, 208, 7, 96, 0, 195, 0, 14, 50, 164, 44
+"MAN EATING MARE", 4, 0, 42, 6, 8, 3, 14, 88, 2, 52, 0, 3, 0, 0, 0, 32, 39
+"MANTICORE ", 4, 1, 40, 6, 6, 4, 12, 88, 2, 28, 0, 3, 0, 3, 20, 42, 26
+"MEDUSA ", 2, 1, 32, 5, 4, 1, 9, 232, 3, 0, 0, 135, 143, 15, 20, 36, 12
+"RAKSHASHA ", 4, 5, 40, 14, 5, 3, 14, 184, 11, 255, 50, 255, 142, 13, 80, 31, 11
+"STONE GOLEM ", 3, 0, 50, 7, 40, 1, 6, 220, 5, 1, 20, 255, 0, 0, 0, 48, 16
+"CAVE TROLL ", 6, 1, 50, 7, 11, 3, 10, 132, 3, 28, 0, 163, 0, 0, 0, 96, 17
+"HILL TROLL ", 5, 2, 50, 8, 12, 3, 11, 76, 4, 10, 0, 179, 0, 0, 0, 96, 17
+"WARLOCK ", 4, 60, 40, 8, 8, 1, 16, 32, 3, 21, 0, 3, 0, 16, 95, 26, 52
+"WEREBEAR ", 4, 10, 45, 8, 8, 4, 14, 32, 3, 0, 0, 135, 137, 0, 0, 160, 31
+"WICKED WITCH ", 4, 50, 30, 4, 6, 2, 14, 232, 3, 3, 0, 3, 151, 10, 40, 26, 12
+"ASSASSIN ", 4, 0, 45, 6, 8, 1, 19, 208, 7, 48, 0, 3, 146, 153, 0, 166, 57
+"BANSHEE ", 2, 1, 40, 10, 10, 1, 12, 184, 11, 0, 128, 135, 145, 8, 40, 52, 62
+"CAVE GIANT ", 6, 5, 50, 10, 16, 3, 12, 208, 7, 60, 0, 3, 0, 158, 0, 42, 17
+"CHIMERA ", 4, 1, 60, 8, 5, 6, 14, 136, 19, 28, 0, 127, 0, 14, 40, 35, 26
+"AIR ELEMENTAL ", 1, 5, 70, 7, 15, 1, 20, 160, 15, 0, 20, 175, 147, 17, 30, 180, 27
+"EXECUTIONER ", 1, 0, 60, 8, 12, 2, 14, 160, 15, 28, 0, 3, 146, 0, 0, 160, 57
+"GORGON ", 4, 5, 55, 8, 12, 1, 12, 112, 23, 0, 0, 3, 143, 11, 40, 35, 45
+"LESSER DEMON ", 4, 0, 40, 10, 8, 4, 16, 196, 9, 125, 20, 255, 145, 9, 15, 244, 59
+"LESSER DEVIL ", 4, 0, 40, 8, 6, 5, 16, 196, 9, 125, 20, 255, 145, 9, 25, 244, 59
+"MUMMY ", 6, 0, 50, 7, 20, 2, 7, 208, 7, 96, 128, 191, 9, 0, 0, 48, 61
+"NECROMANCER ", 4, 1, 35, 7, 8, 2, 17, 208, 7, 63, 40, 3, 0, 18, 95, 42, 54
+"SPECTER ", 6, 0, 47, 8, 12, 1, 12, 184, 11, 0, 128, 143, 17, 0, 0, 48, 58
+"WHITE WOLF ", 6, 0, 42, 10, 12, 3, 14, 196, 9, 4, 0, 19, 9, 27, 30, 50, 29
+"WYVERN ", 6, 5, 45, 7, 18, 2, 12, 208, 7, 38, 0, 3, 149, 0, 0, 32, 46
+"GREEN DRAGON ", 2, 0, 55, 8, 8, 3, 12, 112, 23, 63, 20, 255, 12, 25, 50, 163, 43
+"BLUE DRAGON ", 3, 5, 50, 8, 10, 3, 13, 112, 23, 63, 20, 255, 12, 26, 50, 163, 43
+"EVIL EYE ", 2, 0, 65, 10, 10, 2, 10, 136, 19, 103, 20, 255, 143, 21, 60, 38, 21
+"EARTH ELEMENTAL", 1, 5, 80, 8, 20, 1, 18, 160, 15, 0, 0, 215, 147, 17, 35, 180, 27
+"GHOST ", 3, 0, 60, 10, 10, 1, 10, 160, 15, 0, 128, 135, 16, 0, 0, 48, 62
+"FROST GIANT ", 6, 0, 70, 10, 24, 1, 12, 136, 19, 62, 0, 147, 0, 148, 0, 166, 23
+"STONE GIANT ", 6, 2, 80, 10, 10, 4, 12, 160, 15, 62, 0, 131, 0, 148, 0, 166, 19
+"8 HEADED HYDRA ", 1, 0, 75, 10, 8, 8, 13, 76, 29, 116, 0, 131, 0, 14, 35, 162, 44
+"LAVA BEAST ", 6, 0, 50, 5, 12, 2, 9, 160, 15, 0, 0, 231, 0, 14, 20, 35, 20
+"MANTIS WARRIOR ", 3, 0, 70, 8, 12, 4, 16, 160, 15, 68, 0, 131, 12, 0, 0, 160, 4
+"NAGA ", 3, 0, 65, 8, 8, 1, 15, 160, 15, 60, 25, 131, 136, 8, 40, 22, 35
+"DINOBEETLE ", 4, 0, 200, 10, 50, 1, 8, 112, 23, 28, 0, 131, 0, 0, 0, 160, 3
+"SPHINX ", 2, 50, 60, 11, 10, 3, 18, 136, 19, 63, 40, 255, 7, 8, 40, 22, 34
+"VAMPIRE ", 4, 0, 55, 9, 12, 2, 14, 136, 19, 61, 138, 135, 145, 13, 50, 246, 59
+"WARRIOR ", 4, 1, 75, 12, 12, 2, 14, 160, 15, 38, 0, 131, 0, 148, 0, 168, 50
+"WIZARD ", 2, 1, 60, 8, 6, 2, 18, 88, 27, 39, 0, 139, 0, 19, 95, 42, 52
+"WHITE DRAGON ", 3, 0, 65, 8, 12, 3, 15, 16, 39, 127, 30, 255, 0, 27, 60, 163, 42
+"GRAY DRAGON ", 3, 2, 70, 8, 15, 3, 16, 16, 39, 127, 30, 255, 0, 28, 60, 163, 42
+"ARCH DRUID ", 1, 5, 65, 10, 8, 2, 18, 152, 58, 29, 0, 255, 151, 20, 90, 34, 53
+"CHAOTIC KNIGHT ", 2, 0, 90, 14, 15, 3, 18, 88, 27, 134, 20, 135, 148, 158, 0, 250, 61
+"GREATER DEMON ", 2, 0, 60, 15, 8, 7, 19, 16, 39, 127, 30, 255, 21, 13, 25, 250, 13
+"GREATER DEVIL ", 2, 0, 65, 12, 15, 4, 19, 16, 39, 127, 30, 255, 21, 13, 35, 250, 13
+"FIRE ELEMENTAL ", 1, 5, 90, 9, 30, 1, 20, 64, 31, 0, 0, 199, 147, 17, 40, 180, 27
+"GUARDIAN SPIRIT", 2, 0, 60, 8, 6, 6, 16, 112, 23, 0, 128, 135, 17, 0, 0, 48, 64
+"STORM GIANT ", 4, 1, 100, 9, 30, 2, 14, 16, 39, 198, 0, 167, 0, 19, 40, 38, 23
+"12 HEADED HYDRA", 1, 0, 70, 10, 10, 12, 16, 224, 46, 127, 0, 131, 0, 14, 25, 162, 44
+"INVISIBLE THING", 4, 2, 50, 14, 10, 3, 25, 112, 23, 0, 0, 255, 22, 0, 0, 32, 58
+"MAGE ", 2, 1, 60, 10, 6, 3, 20, 64, 31, 39, 20, 143, 0, 21, 95, 42, 52
+"MASTER THIEF ", 2, 1, 65, 12, 8, 2, 20, 136, 19, 62, 0, 131, 23, 148, 0, 42, 49
+"STEEL GOLEM ", 2, 0, 70, 15, 25, 2, 10, 76, 29, 129, 30, 255, 0, 0, 0, 176, 61
+"WEREPHASE MUMMY", 4, 1, 70, 20, 20, 2, 35, 64, 31, 1, 50, 255, 9, 0, 0, 240, 61
+"BLACK DRAGON ", 2, 0, 75, 12, 18, 3, 16, 152, 58, 127, 30, 255, 135, 29, 70, 163, 41
+"RED DRAGON ", 2, 2, 80, 12, 20, 3, 15, 152, 58, 127, 30, 255, 141, 30, 70, 163, 41
+"XX!XX!XX!XX!XX ", 2, 0, 10, 20, 1, 1, 18, 152, 58, 0, 50, 255, 151, 0, 0, 0, 9
+"BLACK KNIGHT ", 1, 0, 150, 16, 50, 3, 20, 16, 39, 134, 30, 255, 14, 168, 0, 246, 56
+"DEMON LORD ", 1, 0, 150, 20, 50, 2, 30, 96, 234, 255, 50, 255, 24, 23, 20, 246, 13
+"ARCH DEVIL ", 1, 0, 200, 16, 100, 1, 30, 96, 234, 255, 50, 255, 24, 23, 30, 246, 13
+"GOLD DRAGON ", 1, 10, 150, 10, 20, 5, 16, 80, 195, 255, 40, 255, 136, 31, 80, 180, 41
+"SILVER DRAGON ", 2, 0, 90, 8, 16, 4, 16, 32, 78, 255, 40, 255, 136, 31, 80, 180, 41
+"DIAMOND GOLEM ", 2, 0, 100, 15, 60, 3, 12, 152, 58, 1, 40, 255, 0, 0, 0, 48, 16
+"16 HEADED HYDRA", 1, 0, 100, 15, 12, 16, 12, 32, 78, 255, 20, 255, 0, 29, 25, 246, 44
+"HIGH CLERIC ", 1, 5, 100, 14, 16, 3, 18, 16, 39, 127, 20, 131, 0, 22, 80, 36, 54
+"KIRIN ", 1, 50, 90, 15, 40, 4, 22, 176, 54, 135, 30, 255, 25, 9, 25, 42, 26
+"LICH ", 1, 0, 80, 10, 10, 2, 20, 32, 78, 135, 218, 255, 17, 23, 90, 54, 65
+"ARCH MAGE ", 1, 0, 70, 12, 8, 2, 25, 168, 97, 63, 30, 255, 0, 24, 95, 42, 52
+"MASTER ARCHER ", 1, 5, 120, 10, 16, 8, 18, 168, 97, 199, 20, 255, 150, 250, 0, 47, 51
+"PHOENIX ", 1, 50, 150, 13, 8, 3, 24, 152, 58, 129, 10, 255, 144, 14, 60, 42, 27
+"ROC ", 2, 20, 130, 10, 50, 3, 14, 152, 58, 0, 0, 255, 0, 0, 0, 32, 39
+"SAND WORM ", 3, 1, 200, 7, 200, 1, 8, 152, 58, 129, 0, 143, 146, 0, 0, 176, 35
+"TITAN ", 1, 50, 180, 13, 60, 2, 30, 32, 78, 255, 95, 255, 0, 250, 0, 122, 36
+"ALGAE BEAST ", 15, 0, 1, 0, 6, 1, 1, 50, 0, 0, 0, 7, 130, 0, 0, 16, 20
+"WATER RAT ", 15, 0, 3, 1, 6, 1, 6, 100, 0, 0, 0, 6, 130, 0, 0, 16, 6
+"LAMPREY ", 10, 0, 10, 2, 8, 1, 15, 200, 0, 0, 0, 7, 131, 0, 0, 32, 35
+"GIANT LEECH ", 6, 0, 10, 2, 8, 1, 3, 250, 0, 0, 0, 7, 132, 0, 0, 32, 75
+"CROCODILE ", 8, 0, 30, 5, 10, 2, 12, 44, 1, 0, 0, 6, 0, 0, 0, 160, 75
+"GIANT CRAB ", 6, 0, 25, 9, 10, 2, 12, 44, 1, 0, 0, 7, 0, 0, 0, 32, 0
+"BARRACUDA ", 15, 0, 20, 5, 20, 1, 16, 94, 1, 0, 0, 7, 0, 0, 0, 48, 75
+"GIANT SQUID ", 4, 0, 30, 5, 6, 8, 14, 144, 1, 0, 0, 7, 136, 6, 20, 38, 75
+"ELECTRIC EEL ", 10, 0, 30, 5, 8, 1, 15, 244, 1, 0, 0, 47, 136, 10, 20, 47, 75
+"SEA HAG ", 6, 0, 40, 8, 6, 3, 12, 244, 1, 0, 20, 15, 12, 15, 30, 102, 12
+"HIPPOCAMPUS ", 8, 0, 50, 12, 10, 4, 18, 88, 2, 0, 20, 15, 7, 0, 0, 224, 38
+"SHARK ", 15, 0, 40, 6, 30, 2, 24, 188, 2, 0, 0, 15, 0, 0, 0, 176, 75
+"SIREN ", 8, 0, 30, 8, 8, 2, 13, 188, 2, 0, 20, 255, 143, 7, 20, 102, 64
+"WATER ELEMENTAL", 6, 0, 80, 12, 50, 1, 30, 176, 4, 0, 20, 255, 0, 17, 50, 247, 9
+"SEA SERPENT ", 3, 32, 100, 10, 100, 1, 20, 184, 11, 0, 40, 143, 146, 0, 0, 240, 42
+"SEA DRAGON ", 3, 32, 150, 15, 50, 4, 32, 32, 78, 0, 50, 255, 8, 31, 50, 243, 42
+"SCORPION ", 1, 0, 210, 12, 60, 2, 20, 224, 46, 0, 50, 207, 12, 0, 0, 240, 1
+"DARK RIDER ", 1, 0, 210, 15, 50, 4, 30, 224, 46, 0, 90, 127, 17, 19, 20, 255, 56
+"WINGED BEAST ", 1, 0, 210, 12, 120, 1, 30, 224, 46, 0, 50, 159, 8, 0, 0, 240, 46
+"GREAT SEA BEAST", 1, 0, 210, 12, 100, 1, 30, 224, 46, 0, 50, 143, 147, 0, 0, 240, 75
+"DEMON KING ", 1, 0, 240, 30, 50, 5, 35, 80, 195, 255, 120, 255, 24, 23, 30, 255, 73
+"SUCCUBUS QUEEN ", 1, 0, 150, 20, 30, 3, 20, 16, 39, 127, 100, 239, 147, 21, 50, 255, 74
+"TYRANNOSAURUS ", 3, 0, 240, 10, 200, 1, 12, 136, 19, 6, 0, 7, 147, 0, 0, 160, 45
+"ALIEN ", 6, 16, 100, 15, 20, 2, 15, 232, 3, 1, 40, 7, 149, 24, 30, 35, 4
+"NATIVES ", 15, 21, 40, 6, 10, 2, 10, 200, 0, 3, 0, 3, 132, 32, 20, 163, 7
+"VOLCANO GOD ", 1, 0, 220, 30, 40, 6, 32, 96, 234, 255, 120, 255, 24, 13, 50, 255, 20
+"PAUL PEAD ", 1, 0, 100, 10, 30, 1, 19, 208, 7, 61, 50, 143, 14, 13, 40, 243, 50
+"PIRATE ", 15, 0, 40, 8, 20, 1, 17, 244, 1, 7, 10, 135, 138, 0, 0, 176, 58
+"PIRATE CAPTAIN ", 1, 0, 80, 10, 20, 3, 18, 232, 3, 15, 30, 135, 11, 7, 20, 51, 58
+"GRAY MINOTAUR ", 1, 0, 150, 13, 30, 4, 20, 152, 58, 63, 40, 143, 7, 10, 30, 255, 40
+"LORD ARCHER ", 1, 0, 32, 15, 80, 3, 21, 32, 78, 63, 100, 207, 6, 250, 0, 255, 51
+"BRONTASAURUS ", 3, 16, 200, 8, 150, 1, 6, 136, 19, 6, 0, 7, 147, 0, 0, 160, 45
+"STEGOSAURUS ", 3, 5, 200, 15, 200, 1, 6, 136, 19, 6, 0, 7, 147, 0, 0, 160, 45
+"KILLER CADAVER ", 3, 1, 50, 8, 12, 3, 15, 220, 5, 255, 0, 1, 9, 0, 0, 240, 65
+"OKRIM ", 2, 1, 80, 11, 6, 4, 18, 32, 78, 39, 0, 139, 0, 19, 95, 42, 52
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index c2604f04cd6..a4ce29024c4 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -32,6 +32,7 @@ namespace MM1 {
Console::Console() : GUI::Debugger() {
registerCmd("dump_map", WRAP_METHOD(Console, cmdDumpMap));
+ registerCmd("dump_monsters", WRAP_METHOD(Console, cmdDumpMonsters));
registerCmd("map_string", WRAP_METHOD(Console, cmdMapString));
registerCmd("map", WRAP_METHOD(Console, cmdMap));
registerCmd("pos", WRAP_METHOD(Console, cmdPos));
@@ -114,6 +115,39 @@ bool Console::cmdDumpMap(int argc, const char **argv) {
return true;
}
+bool Console::cmdDumpMonsters(int argc, const char **argv) {
+ Common::File f;
+ Common::DumpFile df;
+ if (f.open("mm.exe")) {
+ if (df.open("monsters.txt")) {
+ f.seek(0x1b312);
+
+ for (int i = 0; i < 195; ++i) {
+ Common::String line = "\"";
+ for (int j = 0; j < 15; ++j)
+ line += f.readByte();
+ line += '"';
+
+ for (int j = 0; j < 17; ++j) {
+ line += ", ";
+ line += Common::String::format("%d", f.readByte());
+ }
+
+ df.writeString(line);
+ df.writeByte('\n');
+ }
+
+ df.close();
+ f.close();
+ debugPrintf("Done\n");
+ return true;
+ }
+ }
+
+ debugPrintf("Could not create\n");
+ return true;
+}
+
bool Console::cmdMapString(int argc, const char **argv) {
Common::File f;
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index 7dca6197d93..deddb8486cf 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -35,6 +35,11 @@ protected:
*/
bool cmdDumpMap(int argc, const char **argv);
+ /**
+ * Dumps the monster list
+ */
+ bool cmdDumpMonsters(int argc, const char **argv);
+
/**
* Prints a string from within a map's data segment
*/
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 76fba73e3b4..73b58467674 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -20,13 +20,47 @@
*/
#include "mm/mm1/data/monsters.h"
+#include "common/file.h"
namespace MM {
namespace MM1 {
-const Monster MONSTERS[1] = {
- { "FLESH EATER ", 6, 0, 2, 2, 6, 1, 7, 40, 0, 0, 0, 0, 0x82, 0 }
-};
+bool Monsters::load() {
+ Common::File f;
+ if (!f.open("monsters.txt"))
+ return false;
+
+ for (int lineNum = 0; lineNum < MONSTERS_COUNT; ++lineNum) {
+ Monster &mon = _monsters[lineNum];
+ Common::String line = f.readLine();
+ assert(line.size() > 20 && line[0] == '"' && line[16] == '"');
+
+ mon._name = Common::String(line.c_str() + 1, line.c_str() + 15);
+ line = Common::String(line.c_str() + 17);
+
+ mon._count = getNextValue(line);
+
+ for (int i = 0; i < 16; ++i)
+ mon._attr[i] = getNextValue(line);
+ }
+
+ return true;
+}
+
+byte Monsters::getNextValue(Common::String &line) {
+ // Verify the next comma
+ if (!line.hasPrefix(", "))
+ return 0;
+ line.deleteChar(0);
+ line.deleteChar(0);
+
+ // Get the value
+ byte result = atoi(line.c_str());
+ while (!line.empty() && Common::isDigit(line.firstChar()))
+ line.deleteChar(0);
+
+ return result;
+}
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 49acc4f5176..2fc4d5a2cf3 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -22,18 +22,41 @@
#ifndef MM1_DATA_MONSTERS_H
#define MM1_DATA_MONSTERS_H
-#include "common/scummsys.h"
+#include "common/str.h"
namespace MM {
namespace MM1 {
+#define MONSTERS_COUNT 195
+
struct Monster {
- const char *_name; // char _name[15];
+ Common::String _name; // char _name[15];
byte _count;
byte _attr[16];
};
-extern const Monster MONSTERS[1];
+class Monsters {
+private:
+ Monster _monsters[MONSTERS_COUNT];
+
+private:
+ /**
+ * Get the next value from a read line
+ */
+ byte getNextValue(Common::String &line);
+public:
+ Monsters() {}
+
+ /**
+ * Load the monster list
+ */
+ bool load();
+
+ const Monster &operator[](uint i) {
+ assert(i >= 1 && i <= MONSTERS_COUNT);
+ return _monsters[i];
+ }
+};
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 6a8e985133b..1109f82db04 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -124,7 +124,7 @@ exit_loop:
// Add monster details to list
_val11 = _arr1[i];
assert(_val11 == 1);
- const Monster &mons = MONSTERS[_arr2[i]];
+ const Monster &mons = g_globals->_monsters[_arr2[i]];
_monsterList.push_back(mons);
if (_val11 > _val9) {
@@ -154,12 +154,12 @@ void Encounter::randomAdjust() {
const Monster *Encounter::getMonster() {
assert(_randVal > 0);
- return &MONSTERS[_randVal - 1];
+ return &g_globals->_monsters[_randVal];
}
void Encounter::getMonsterVal() {
assert(_val11 == 1 && _randVal > 0);
- _monsterValP = &MONSTERS[_randVal - 1]._attr[(_val11 - 8) * 2];
+ _monsterValP = &g_globals->_monsters[_randVal]._attr[(_val11 - 8) * 2];
}
} // namespace Game
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 70a44c8b611..91432d2f0b5 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -52,6 +52,9 @@ bool Globals::load(bool isEnhanced) {
if (!_font.load("font.bmp"))
return false;
+ if (!_monsters.load())
+ return false;
+
// Load roster
_roster.load();
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 3f324f3d394..60feb0ff508 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -29,6 +29,7 @@
#include "mm/xeen/sprites.h"
#include "mm/mm1/data/game_state.h"
#include "mm/mm1/data/items.h"
+#include "mm/mm1/data/monsters.h"
#include "mm/mm1/data/roster.h"
#include "mm/mm1/game/encounter.h"
#include "mm/mm1/maps/maps.h"
@@ -48,6 +49,7 @@ public:
BitmapFont _font;
bool _heardRumor = false;
Game::Encounter _encounters;
+ Monsters _monsters;
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
Commit: eca200de317f967d624f4a28880ab69bbb910eed
https://github.com/scummvm/scummvm/commit/eca200de317f967d624f4a28880ab69bbb910eed
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: In progress experiments decoding monster images
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 73b58467674..758bb5de724 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -20,6 +20,8 @@
*/
#include "mm/mm1/data/monsters.h"
+#include "mm/mm1/gfx/dta.h"
+#include "mm/mm1/gfx/screen_decoder.h"
#include "common/file.h"
namespace MM {
@@ -62,5 +64,21 @@ byte Monsters::getNextValue(Common::String &line) {
return result;
}
+Graphics::ManagedSurface Monsters::getMonsterImage(int monsterNum) {
+ Common::SeekableReadStream *entry = _monPix.load(monsterNum);
+ //entry->skip(2);
+ byte v1 = entry->readByte();
+ byte v2 = entry->readByte();
+ debug("%d %d", v1, v2);
+
+ // Decode the image
+ Graphics::ManagedSurface img;
+ Gfx::ScreenDecoder decoder;
+ if (!decoder.loadStream(*entry, 105, 105))
+ error("Failed decoding monster image");
+
+ return img;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 2fc4d5a2cf3..b5285664ecf 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -22,7 +22,9 @@
#ifndef MM1_DATA_MONSTERS_H
#define MM1_DATA_MONSTERS_H
+#include "mm/mm1/gfx/dta.h"
#include "common/str.h"
+#include "graphics/managed_surface.h"
namespace MM {
namespace MM1 {
@@ -38,24 +40,32 @@ struct Monster {
class Monsters {
private:
Monster _monsters[MONSTERS_COUNT];
-
+ Gfx::DTA _monPix;
private:
/**
* Get the next value from a read line
*/
byte getNextValue(Common::String &line);
public:
- Monsters() {}
+ Monsters() : _monPix(MONPIX_DTA) {}
/**
* Load the monster list
*/
bool load();
+ /**
+ * Square brackets operator
+ */
const Monster &operator[](uint i) {
assert(i >= 1 && i <= MONSTERS_COUNT);
return _monsters[i];
}
+
+ /**
+ * Get a monster image
+ */
+ Graphics::ManagedSurface getMonsterImage(int monsterNum);
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 1109f82db04..aabde8701a2 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -64,7 +64,7 @@ void Encounter::execute() {
if (maxRand >= 2) {
int highestRand = map[33];
maxRand = MIN(maxRand, highestRand);
- comp = g_engine->getRandomNumber(maxRand);
+ comp = g_engine->getRandomNumber(1, maxRand);
} else {
comp = 1;
}
@@ -79,7 +79,7 @@ void Encounter::execute() {
_val11 = comp;
_levelIndex += comp;
- _randVal = g_engine->getRandomNumber(16);
+ _randVal = g_engine->getRandomNumber(1, 16);
_arr2[_val5] = _randVal;
_val5 = (_val5 + 1) & 0xff;
@@ -89,7 +89,7 @@ void Encounter::execute() {
assert(_val11 == 1);
monsterP = getMonster();
- maxVal = g_engine->getRandomNumber(monsterP->_count);
+ maxVal = g_engine->getRandomNumber(1, monsterP->_count);
for (int i = 0; i < maxVal; ++i) {
assert(_val5 > 0);
@@ -118,7 +118,7 @@ exit_loop:
// result in an invalid monster offset calculated
warning("TODO: Nonsensical monster offset set");
_arr1[i] = 10;
- _arr2[i] = g_engine->getRandomNumber(15);
+ _arr2[i] = g_engine->getRandomNumber(1, 15);
}
// Add monster details to list
@@ -138,7 +138,7 @@ exit_loop:
}
void Encounter::randomAdjust() {
- int rval = g_engine->getRandomNumber(100);
+ int rval = g_engine->getRandomNumber(1, 100);
_val6 = 0;
if (rval < 51) {
@@ -153,7 +153,6 @@ void Encounter::randomAdjust() {
}
const Monster *Encounter::getMonster() {
- assert(_randVal > 0);
return &g_globals->_monsters[_randVal];
}
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 335753cd49b..bde780377c0 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -44,11 +44,18 @@ void Encounter::draw() {
}
// Display the monster
+ drawMonster(enc._val8);
// Write the encounter options
}
+void Encounter::drawMonster(int monsterNum) {
+ Graphics::ManagedSurface img =
+ g_globals->_monsters.getMonsterImage(monsterNum);
+ getSurface().blitFrom(img, Common::Point(20, 20));
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index 23c91b21945..0b21b980803 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -30,10 +30,19 @@ namespace MM1 {
namespace Views {
class Encounter : public TextView {
+private:
+ /**
+ * Draws a monster
+ */
+ void drawMonster(int monsterNum);
public:
Encounter();
virtual ~Encounter() {}
+ /**
+ * Draw the encounter details overlayed on
+ * the existing game screen
+ */
void draw() override;
};
Commit: 7dd5f4f2a04e1ff2b244ce60ac623ed2c7a506a1
https://github.com/scummvm/scummvm/commit/7dd5f4f2a04e1ff2b244ce60ac623ed2c7a506a1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: Figured out confusion with Encounter _val11
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 758bb5de724..e9a568061ad 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -40,10 +40,8 @@ bool Monsters::load() {
mon._name = Common::String(line.c_str() + 1, line.c_str() + 15);
line = Common::String(line.c_str() + 17);
- mon._count = getNextValue(line);
-
- for (int i = 0; i < 16; ++i)
- mon._attr[i] = getNextValue(line);
+ for (int i = 0; i < 17; ++i)
+ mon._counts[i] = getNextValue(line);
}
return true;
@@ -65,6 +63,7 @@ byte Monsters::getNextValue(Common::String &line) {
}
Graphics::ManagedSurface Monsters::getMonsterImage(int monsterNum) {
+ monsterNum = 1; //***DEBUG***
Common::SeekableReadStream *entry = _monPix.load(monsterNum);
//entry->skip(2);
byte v1 = entry->readByte();
@@ -74,7 +73,7 @@ Graphics::ManagedSurface Monsters::getMonsterImage(int monsterNum) {
// Decode the image
Graphics::ManagedSurface img;
Gfx::ScreenDecoder decoder;
- if (!decoder.loadStream(*entry, 105, 105))
+ if (!decoder.loadStream(*entry, 104, 96))
error("Failed decoding monster image");
return img;
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index b5285664ecf..1f4ae134ba0 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -33,8 +33,7 @@ namespace MM1 {
struct Monster {
Common::String _name; // char _name[15];
- byte _count;
- byte _attr[16];
+ byte _counts[17];
};
class Monsters {
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index aabde8701a2..d16625866a1 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -32,8 +32,7 @@ namespace Game {
void Encounter::execute() {
Maps::Map &map = *g_maps->_currentMap;
- int comp, maxRand, maxVal;
- const Monster *monsterP;
+ int comp, maxRand, maxVal, monsterCount;
_val1 = _val2 = _val3 = 0;
if (!_flag) {
@@ -87,9 +86,8 @@ void Encounter::execute() {
if (_val5 >= map[34])
goto exit_loop;
- assert(_val11 == 1);
- monsterP = getMonster();
- maxVal = g_engine->getRandomNumber(1, monsterP->_count);
+ monsterCount = getMonsterCount();
+ maxVal = g_engine->getRandomNumber(1, monsterCount);
for (int i = 0; i < maxVal; ++i) {
assert(_val5 > 0);
@@ -114,9 +112,6 @@ exit_loop:
for (int i = 0; i < _val5; ++i) {
maxVal = (_arr1[i] - 1) * 16 + _arr2[i];
if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
- // TODO: This section doesn't make sense, since it will
- // result in an invalid monster offset calculated
- warning("TODO: Nonsensical monster offset set");
_arr1[i] = 10;
_arr2[i] = g_engine->getRandomNumber(1, 15);
}
@@ -129,8 +124,8 @@ exit_loop:
if (_val11 > _val9) {
_val9 = _val11;
- _val10 = mons._attr[0];
- _val8 = mons._attr[15];
+ _val10 = mons._counts[1];
+ _val8 = mons._counts[16];
}
}
@@ -153,12 +148,13 @@ void Encounter::randomAdjust() {
}
const Monster *Encounter::getMonster() {
+ assert(_randVal > 0);
return &g_globals->_monsters[_randVal];
}
-void Encounter::getMonsterVal() {
- assert(_val11 == 1 && _randVal > 0);
- _monsterValP = &g_globals->_monsters[_randVal]._attr[(_val11 - 8) * 2];
+byte Encounter::getMonsterCount() {
+ assert(_val11 >= 1 && _val11 <= 8);
+ return getMonster()->_counts[(_val11 - 1) * 2];
}
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 1e880921242..d6590b1792d 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -39,11 +39,10 @@ private:
int _totalLevels = 0, _highestLevel = 0;
int _randVal = 0;
byte _arr1[15], _arr2[15];
- const byte *_monsterValP;
void randomAdjust();
const Monster *getMonster();
- void getMonsterVal();
+ byte getMonsterCount();
public:
Common::Array<Monster> _monsterList;
int _val8 = 0;
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index bde780377c0..e698a7398ad 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -48,6 +48,7 @@ void Encounter::draw() {
// Write the encounter options
+ getSurface().markAllDirty();
}
void Encounter::drawMonster(int monsterNum) {
Commit: 49b1c776b5ea53c5b88c2a21e6acd90eb2053df8
https://github.com/scummvm/scummvm/commit/49b1c776b5ea53c5b88c2a21e6acd90eb2053df8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: Monster images are now displaying
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index e9a568061ad..53520cd0ea4 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -63,12 +63,8 @@ byte Monsters::getNextValue(Common::String &line) {
}
Graphics::ManagedSurface Monsters::getMonsterImage(int monsterNum) {
- monsterNum = 1; //***DEBUG***
Common::SeekableReadStream *entry = _monPix.load(monsterNum);
- //entry->skip(2);
- byte v1 = entry->readByte();
- byte v2 = entry->readByte();
- debug("%d %d", v1, v2);
+ entry->skip(2);
// Decode the image
Graphics::ManagedSurface img;
@@ -76,6 +72,8 @@ Graphics::ManagedSurface Monsters::getMonsterImage(int monsterNum) {
if (!decoder.loadStream(*entry, 104, 96))
error("Failed decoding monster image");
+ img.copyFrom(decoder.getSurface());
+
return img;
}
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index e698a7398ad..6f48c81aca2 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -48,13 +48,12 @@ void Encounter::draw() {
// Write the encounter options
- getSurface().markAllDirty();
}
void Encounter::drawMonster(int monsterNum) {
Graphics::ManagedSurface img =
g_globals->_monsters.getMonsterImage(monsterNum);
- getSurface().blitFrom(img, Common::Point(20, 20));
+ getSurface().blitFrom(img, Common::Point(64, 16));
}
} // namespace Views
Commit: 8c08892c03dfbfeca43dde90bc0a8f29110de929
https://github.com/scummvm/scummvm/commit/8c08892c03dfbfeca43dde90bc0a8f29110de929
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: Starting to flesh out encounter view
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/encounter.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index f77eb17a6c6..96e1f9b9307 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -267,6 +267,9 @@
location_facing: "FACING: "
teleport_dir: "DIRECTION (N,E,S,W): "
teleport_squares: "# OF SQUARES (0-9): "
+ encounter:
+ title: " ENCOUNTER! "
+ surprised: "THE MONSTERS SURPRISED YOU!"
enhdialogs:
character:
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index d6590b1792d..4c3e0e68fbd 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -29,6 +29,10 @@ namespace MM {
namespace MM1 {
namespace Game {
+enum EncounterType {
+ FORCE_SURPRISED = -1, NORMAL_SURPRISED = 0, NORMAL_ENCOUNTER = 1
+};
+
struct Encounter {
private:
bool _flag = false;
@@ -46,6 +50,7 @@ private:
public:
Common::Array<Monster> _monsterList;
int _val8 = 0;
+ EncounterType _encounterFlag = NORMAL_SURPRISED;
public:
void execute();
};
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 99be8ee74f3..da776f68f0c 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -58,12 +58,12 @@ darkness:
}
// Encounter checks
- _encounterFlag = false;
+ g_globals->_encounters._encounterFlag = NORMAL_SURPRISED;
if (maps._currentState & 0x80) {
map.special();
} else if (_stepRandom) {
- _encounterFlag = true;
+ g_globals->_encounters._encounterFlag = NORMAL_ENCOUNTER;
_stepRandom = false;
g_globals->_encounters.execute();
} else {
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index dca05ef0e19..55b0b7be95c 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -40,7 +40,6 @@ protected:
int _businessDisplay = -1;
byte _arr2[8];
bool _stepRandom = false;
- bool _encounterFlag = false;
private:
/**
* Turn left
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 6f48c81aca2..b85b00d2803 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -20,7 +20,9 @@
*/
#include "mm/mm1/views/encounter.h"
+#include "mm/mm1/game/encounter.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
namespace MM {
namespace MM1 {
@@ -29,9 +31,33 @@ namespace Views {
Encounter::Encounter() : TextView("Encounter") {
}
+bool Encounter::msgFocus(const FocusMessage &msg) {
+ _mode = ALERT;
+ return true;
+}
+
void Encounter::draw() {
const Game::Encounter &enc = g_globals->_encounters;
+ switch (_mode) {
+ case ALERT:
+ writeString(9, 6, " ");
+ writeString(9, 7, STRING["dialogs.encounter.title"]);
+ writeString(9, 8, " ");
+
+ delaySeconds(2);
+ break;
+
+ case SURPRISED_BY_MONSTERS:
+ writeString(6, 21, STRING["dialogs.encounter.surprised"]);
+ delaySeconds(2);
+ break;
+
+ case NORMAL_ENCOUNTER:
+
+ break;
+ }
+
// Clear the commands area
Graphics::ManagedSurface s = getSurface();
s.fillRect(Common::Rect(31 * 8, 0, 320, 17 * 8), 0);
@@ -56,6 +82,32 @@ void Encounter::drawMonster(int monsterNum) {
getSurface().blitFrom(img, Common::Point(64, 16));
}
+void Encounter::timeout() {
+ Game::Encounter &enc = g_globals->_encounters;
+ const Maps::Map &map = *g_maps->_currentMap;
+
+ switch (_mode) {
+ case ALERT:
+ // Finished displaying initial encounter alert
+ if (enc._encounterFlag < 0 /* FORCE_SURPRISED */ ||
+ ((enc._encounterFlag == Game::NORMAL_SURPRISED ||
+ /* NORMAL_ENCOUNTER */
+ g_engine->getRandomNumber(1, 100) > map[21]) &&
+ (!g_globals->_spells._s.guard_dog ||
+ g_engine->getRandomNumber(1, 100) > map[20]))
+ ) {
+ _mode = SURPRISED_BY_MONSTERS;
+ enc._encounterFlag = Game::FORCE_SURPRISED;
+ } else {
+ _mode = NORMAL_ENCOUNTER;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index 0b21b980803..6e87ee3f439 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -31,6 +31,12 @@ namespace Views {
class Encounter : public TextView {
private:
+ enum Mode {
+ ALERT, SURPRISED_BY_MONSTERS, SURPRISED_MONSTERS,
+ NORMAL_ENCOUNTER
+ };
+ Mode _mode = ALERT;
+
/**
* Draws a monster
*/
@@ -39,11 +45,21 @@ public:
Encounter();
virtual ~Encounter() {}
+ /**
+ * Called when the view is focused
+ */
+ bool msgFocus(const FocusMessage &msg) override;
+
/**
* Draw the encounter details overlayed on
* the existing game screen
*/
void draw() override;
+
+ /**
+ * Handles delay timeouts
+ */
+ void timeout() override;
};
} // namespace Views
Commit: 1e3232ed25c6a442096cc52214212bac6fe60891
https://github.com/scummvm/scummvm/commit/1e3232ed25c6a442096cc52214212bac6fe60891
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: Implementing encounter options
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 96e1f9b9307..814c34fc012 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -270,6 +270,11 @@
encounter:
title: " ENCOUNTER! "
surprised: "THE MONSTERS SURPRISED YOU!"
+ surprise: "YOU SURPRISED A GROUP OF MONSTERS,"
+ approach: "APPROACH (Y/N)?"
+ options1: "OPTIONS: 'A' ATTACK 'R' RETREAT"
+ options2: "'B' BRIBE 'S' SURRENDER"
+ surrender_failed: "THE MONSTERS DON'T TAKE PRISONERS!"
enhdialogs:
character:
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 50c8fe99964..f4933797cde 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -58,6 +58,21 @@ uint Party::getPartyGold() const {
return total;
}
+void Party::clearPartyGold() {
+ for (uint i = 0; i < size(); ++i)
+ (*this)[i]._gold = 0;
+}
+
+void Party::clearPartyGems() {
+ for (uint i = 0; i < size(); ++i)
+ (*this)[i]._gems = 0;
+}
+
+void Party::clearPartyFood() {
+ for (uint i = 0; i < size(); ++i)
+ (*this)[i]._food = 0;
+}
+
void Party::updateAC() {
for (uint i = 0; i < size(); ++i)
(*this)[i].updateAC();
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index 30d3d07406c..c1227030f4f 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -39,6 +39,21 @@ struct Party : public Common::Array<Character> {
*/
uint getPartyGold() const;
+ /**
+ * Reset entire party's gold to zero
+ */
+ void clearPartyGold();
+
+ /**
+ * Reset entire party's gems to zero
+ */
+ void clearPartyGems();
+
+ /**
+ * Reset entire party's food to zero
+ */
+ void clearPartyFood();
+
/**
* Update the entire party AC
*/
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index dd418dc4c6e..ec0e17c9221 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -265,6 +265,14 @@ Graphics::ManagedSurface UIElement::getSurface() const {
return Graphics::ManagedSurface(*g_events->getScreen(), _bounds);
}
+int UIElement::getRandomNumber(int minNumber, int maxNumber) {
+ return g_engine->getRandomNumber(maxNumber - minNumber + 1) + minNumber;
+}
+
+int UIElement::getRandomNumber(int maxNumber) {
+ return g_engine->getRandomNumber(maxNumber);
+}
+
void UIElement::delaySeconds(uint seconds) {
_timeoutCtr = seconds * FRAME_RATE;
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index d026dc5359f..2279746f32a 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -153,6 +153,12 @@ public:
void addView();
void open() { addView(); }
+ /**
+ * Returns a random number
+ */
+ int getRandomNumber(int minNumber, int maxNumber);
+ int getRandomNumber(int maxNumber);
+
/**
* Sets the element's bounds
*/
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index d16625866a1..cb9a31bd3f2 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -40,7 +40,7 @@ void Encounter::execute() {
}
_totalLevels = _highestLevel = 0;
- _val6 = _val8 = _val9 = _val10 = 0;
+ _val6 = _val8 = _val9 = _fleeThreshold = 0;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
const Character &c = g_globals->_party[i];
@@ -124,7 +124,7 @@ exit_loop:
if (_val11 > _val9) {
_val9 = _val11;
- _val10 = mons._counts[1];
+ _fleeThreshold = mons._counts[1];
_val8 = mons._counts[16];
}
}
@@ -157,6 +157,10 @@ byte Encounter::getMonsterCount() {
return getMonster()->_counts[(_val11 - 1) * 2];
}
+bool Encounter::checkSurroundParty() const {
+ return g_engine->getRandomNumber(1, 100) > _fleeThreshold;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 4c3e0e68fbd..faee101ee9d 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -37,8 +37,8 @@ struct Encounter {
private:
bool _flag = false;
int _val1 = 0, _val2 = 0, _val3 = 0;
- int _levelIndex = 0, _val5 = 0, _val6 = 0;
- int _val9 = 0, _val10 = 0;
+ int _levelIndex = 0, _val6 = 0;
+ int _val9 = 0;
int _val11 = 0;
int _totalLevels = 0, _highestLevel = 0;
int _randVal = 0;
@@ -49,10 +49,19 @@ private:
byte getMonsterCount();
public:
Common::Array<Monster> _monsterList;
- int _val8 = 0;
+ int _val5 = 0, _val8 = 0;
EncounterType _encounterFlag = NORMAL_SURPRISED;
+ byte _fleeThreshold = 0;
public:
+ /**
+ * Start an encounter
+ */
void execute();
+
+ /**
+ * Chooses whether an encounter can be fleed
+ */
+ bool checkSurroundParty() const;
};
} // namespace Game
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 85c86c18582..493fd1a41b5 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -36,6 +36,15 @@ namespace Maps {
class Maps;
+enum DataOffset {
+ MAP_FLEE_THRESHOLD = 22,
+ MAP_FLEE_X = 23,
+ MAP_FLEE_Y = 24,
+ MAP_SURRENDER_THRESHOLD = 25,
+ MAP_SURRENDER_X = 26,
+ MAP_SURRENDER_Y = 27
+};
+
enum WallType {
WALL_NONE = 0, WALL_NORMAL = 1, WALL_DOOR = 2,
WALL_TORCH = 3
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index b85b00d2803..9f178718fe8 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -37,7 +37,7 @@ bool Encounter::msgFocus(const FocusMessage &msg) {
}
void Encounter::draw() {
- const Game::Encounter &enc = g_globals->_encounters;
+ Game::Encounter &enc = g_globals->_encounters;
switch (_mode) {
case ALERT:
@@ -50,30 +50,52 @@ void Encounter::draw() {
case SURPRISED_BY_MONSTERS:
writeString(6, 21, STRING["dialogs.encounter.surprised"]);
+ enc._encounterFlag = Game::FORCE_SURPRISED;
delaySeconds(2);
break;
- case NORMAL_ENCOUNTER:
+ case SURPRISED_MONSTERS:
+ writeString(2, 21, STRING["dialogs.encounter.surprise"]);
+ writeString(1, 22, STRING["dialogs.encounter.surprise"]);
+ break;
+
+ case ENCOUNTER_OPTIONS: {
+ // Clear the commands area
+ Graphics::ManagedSurface s = getSurface();
+ s.fillRect(Common::Rect(31 * 8, 0, 320, 17 * 8), 0);
+ // Write the encounter options
+ clearLines(20, 24);
+ writeString(0, 21, STRING["dialogs.encounter.option1"]);
+ writeString(10, 22, STRING["dialogs.encounter.option2"]);
break;
}
- // Clear the commands area
- Graphics::ManagedSurface s = getSurface();
- s.fillRect(Common::Rect(31 * 8, 0, 320, 17 * 8), 0);
+ case NOWHERE_TO_RUN:
+ clearLines(20, 24);
+ writeString(11, 21, STRING["dialogs.encounter.nowhere_to_run"]);
+ delaySeconds(2);
+ break;
- // Write the monster list
- for (uint i = 0; i < enc._monsterList.size(); ++i) {
- writeChar(22, i, 'A' + i);
- writeString(") ");
- writeString(enc._monsterList[i]._name);
- }
+ case SURRENDER_FAILED:
+ clearLines(20, 24);
+ writeString(2, 21, STRING["dialogs.encounter.surrender_failed"]);
- // Display the monster
- drawMonster(enc._val8);
+ default:
+ break;
+ }
- // Write the encounter options
+ if (_mode != ALERT) {
+ // Display the monster
+ drawMonster(enc._val8);
+ // Write the monster list
+ for (uint i = 0; i < enc._monsterList.size(); ++i) {
+ writeChar(22, i, 'A' + i);
+ writeString(") ");
+ writeString(enc._monsterList[i]._name);
+ }
+ }
}
void Encounter::drawMonster(int monsterNum) {
@@ -83,31 +105,148 @@ void Encounter::drawMonster(int monsterNum) {
}
void Encounter::timeout() {
- Game::Encounter &enc = g_globals->_encounters;
+ const Game::Encounter &enc = g_globals->_encounters;
const Maps::Map &map = *g_maps->_currentMap;
switch (_mode) {
case ALERT:
// Finished displaying initial encounter alert
- if (enc._encounterFlag < 0 /* FORCE_SURPRISED */ ||
- ((enc._encounterFlag == Game::NORMAL_SURPRISED ||
- /* NORMAL_ENCOUNTER */
- g_engine->getRandomNumber(1, 100) > map[21]) &&
- (!g_globals->_spells._s.guard_dog ||
- g_engine->getRandomNumber(1, 100) > map[20]))
- ) {
+ if (enc._encounterFlag < 0 /* FORCE_SURPRISED */) {
_mode = SURPRISED_BY_MONSTERS;
- enc._encounterFlag = Game::FORCE_SURPRISED;
+ } else if (enc._encounterFlag == Game::NORMAL_SURPRISED ||
+ /* ENCOUNTER_OPTIONS */
+ g_engine->getRandomNumber(1, 100) > map[21]) {
+ // Potentially surprised. Check for guard dog spell
+ if (g_globals->_spells._s.guard_dog ||
+ g_engine->getRandomNumber(1, 100) > map[20])
+ _mode = ENCOUNTER_OPTIONS;
+ else
+ _mode = SURPRISED_BY_MONSTERS;
} else {
- _mode = NORMAL_ENCOUNTER;
+ _mode = SURPRISED_MONSTERS;
}
break;
+ case NOWHERE_TO_RUN:
+ case SURRENDER_FAILED:
+ _mode = BATTLE;
+ break;
+
default:
break;
}
+
+ redraw();
}
+bool Encounter::msgKeypress(const KeypressMessage &msg) {
+ switch (_mode) {
+ case SURPRISED_MONSTERS:
+ if (msg.keycode == Common::KEYCODE_y) {
+ _mode = ENCOUNTER_OPTIONS;
+ redraw();
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ encounterEnded();
+ }
+ break;
+
+ case ENCOUNTER_OPTIONS:
+ switch (msg.keycode) {
+ case Common::KEYCODE_a:
+ attack();
+ break;
+ case Common::KEYCODE_b:
+ bribe();
+ break;
+ case Common::KEYCODE_r:
+ retreat();
+ break;
+ case Common::KEYCODE_s:
+ surrender();
+ break;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Encounter::encounterEnded() {
+ close();
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void Encounter::attack() {
+
+}
+
+void Encounter::bribe() {
+
+}
+
+void Encounter::retreat() {
+ const Game::Encounter &enc = g_globals->_encounters;
+ int val = getRandomNumber(1, 110);
+
+ if (val >= 100) {
+ flee();
+ } else if (val > Maps::MAP_FLEE_THRESHOLD) {
+ _mode = NOWHERE_TO_RUN;
+ redraw();
+ } else if (enc._val5 < (int)g_globals->_party.size() || !enc.checkSurroundParty()) {
+ flee();
+ }
+}
+
+void Encounter::surrender() {
+ const Game::Encounter &enc = g_globals->_encounters;
+ const Maps::Map &map = *g_maps->_currentMap;
+
+ if (getRandomNumber(1, 100) > map[Maps::MAP_SURRENDER_THRESHOLD] ||
+ getRandomNumber(1, 100) > enc._fleeThreshold) {
+ _mode = SURRENDER_FAILED;
+ redraw();
+ } else {
+ g_maps->_mapPos.x = map[Maps::MAP_SURRENDER_X];
+ g_maps->_mapPos.y = map[Maps::MAP_SURRENDER_Y];
+
+ // Randomly remove food, gems, or gold from the party
+ int val = getRandomNumber(1, 200);
+ if (val < 51) {
+ } else if (val < 151) {
+ g_globals->_party.clearPartyGold();
+ } else if (val < 161) {
+ g_globals->_party.clearPartyGems();
+ } else if (val < 171) {
+ g_globals->_party.clearPartyFood();
+ } else if (val < 191) {
+ g_globals->_party.clearPartyFood();
+ g_globals->_party.clearPartyGold();
+ } else if (val < 200) {
+ g_globals->_party.clearPartyGold();
+ g_globals->_party.clearPartyGems();
+ } else {
+ g_globals->_party.clearPartyGems();
+ g_globals->_party.clearPartyFood();
+ g_globals->_party.clearPartyGold();
+ }
+
+ encounterEnded();
+ }
+}
+
+void Encounter::flee() {
+ const Maps::Map &map = *g_maps->_currentMap;
+ g_maps->_mapPos.x = map[Maps::MAP_FLEE_X];
+ g_maps->_mapPos.y = map[Maps::MAP_FLEE_Y];
+ encounterEnded();
+}
+
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index 6e87ee3f439..f7d99e9fb27 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -33,7 +33,9 @@ class Encounter : public TextView {
private:
enum Mode {
ALERT, SURPRISED_BY_MONSTERS, SURPRISED_MONSTERS,
- NORMAL_ENCOUNTER
+ ENCOUNTER_OPTIONS, NOWHERE_TO_RUN, SURRENDER_FAILED,
+
+ BATTLE
};
Mode _mode = ALERT;
@@ -41,6 +43,16 @@ private:
* Draws a monster
*/
void drawMonster(int monsterNum);
+
+ /**
+ * Handles the end of the encounter
+ */
+ void encounterEnded();
+ void attack();
+ void bribe();
+ void retreat();
+ void surrender();
+ void flee();
public:
Encounter();
virtual ~Encounter() {}
@@ -60,6 +72,11 @@ public:
* Handles delay timeouts
*/
void timeout() override;
+
+ /**
+ * Handles keypresses
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace Views
Commit: f842f9e7441f7e03fdbf482f0b1ab0efd66f0dc7
https://github.com/scummvm/scummvm/commit/f842f9e7441f7e03fdbf482f0b1ab0efd66f0dc7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: More encounter options implementation
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views_enh/locations/temple.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 814c34fc012..9953ccfe9cf 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -275,6 +275,13 @@
options1: "OPTIONS: 'A' ATTACK 'R' RETREAT"
options2: "'B' BRIBE 'S' SURRENDER"
surrender_failed: "THE MONSTERS DON'T TAKE PRISONERS!"
+ no_response: "NO RESPONSE"
+ give_up: "GIVE UP ALL YOUR %s (Y/N)?"
+ gems: "GEMS"
+ food: "FOOD"
+ gold: "GOLD"
+ not_enough: "NOT ENOUGH"
+ alignment_slips: "*** ALIGNMENT SLIPS ***"
enhdialogs:
character:
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 956e5911bcc..814643e8ec2 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -182,7 +182,7 @@ void Character::clear() {
_arr58._s._v62.clear();
_arr58._s._v64.clear();
_arr58._s._v66.clear();
- _v6c = _v6f = 0;
+ _v6c = _alignmentCtr = 0;
}
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 25740dfa9cd..c5e5b3b87b2 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -235,7 +235,7 @@ struct Character {
// TODO: Figure out what these are
Arr58 _arr58;
- int _v68, _v69, _v6a, _v6b, _v6c, _v6e, _v6f;
+ int _v68, _v69, _v6a, _v6b, _v6c, _v6e, _alignmentCtr;
byte _quest = 0;
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index cb9a31bd3f2..7e74d3a2cf1 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -161,6 +161,13 @@ bool Encounter::checkSurroundParty() const {
return g_engine->getRandomNumber(1, 100) > _fleeThreshold;
}
+void Encounter::changeCharAlignment(Alignment align) {
+ if (g_globals->_currCharacter->_alignment != align) {
+ g_globals->_currCharacter->_alignment = align;
+ ++_val2;
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index faee101ee9d..c1448c3dc01 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -23,6 +23,7 @@
#define MM1_GAME_ENCOUNTER_H
#include "common/array.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/data/monsters.h"
namespace MM {
@@ -36,7 +37,6 @@ enum EncounterType {
struct Encounter {
private:
bool _flag = false;
- int _val1 = 0, _val2 = 0, _val3 = 0;
int _levelIndex = 0, _val6 = 0;
int _val9 = 0;
int _val11 = 0;
@@ -49,7 +49,8 @@ private:
byte getMonsterCount();
public:
Common::Array<Monster> _monsterList;
- int _val5 = 0, _val8 = 0;
+ int _val1 = 0, _val2 = 0;
+ int _val3 = 0, _val5 = 0, _val8 = 0;
EncounterType _encounterFlag = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
public:
@@ -62,6 +63,8 @@ public:
* Chooses whether an encounter can be fleed
*/
bool checkSurroundParty() const;
+
+ void changeCharAlignment(Alignment align);
};
} // namespace Game
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 493fd1a41b5..0a913a54a29 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -42,7 +42,8 @@ enum DataOffset {
MAP_FLEE_Y = 24,
MAP_SURRENDER_THRESHOLD = 25,
MAP_SURRENDER_X = 26,
- MAP_SURRENDER_Y = 27
+ MAP_SURRENDER_Y = 27,
+ MAP_BRIBE_THRESHOLD = 28
};
enum WallType {
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 93695679074..0185bc21099 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -126,7 +126,7 @@ void CreateCharacters::NewCharacter::save() {
re._food = 10;
re._backpack[0]._id = 1;
const int ALIGNMENT_VALS[3] = { 0, 0x10, 0x20 };
- re._v6f = ALIGNMENT_VALS[re._alignmentInitial];
+ re._alignmentCtr = ALIGNMENT_VALS[re._alignmentInitial];
g_globals->_roster.save();
}
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 9f178718fe8..5d9a70676c0 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -23,6 +23,7 @@
#include "mm/mm1/game/encounter.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -80,6 +81,28 @@ void Encounter::draw() {
case SURRENDER_FAILED:
clearLines(20, 24);
writeString(2, 21, STRING["dialogs.encounter.surrender_failed"]);
+ delaySeconds(2);
+ break;
+
+ case NO_RESPONSE:
+ clearLines(20, 24);
+ writeString(12, 21, STRING["dialogs.encounter.no_response"]);
+ delaySeconds(2);
+ break;
+
+ case BRIBE:
+ enc._val1++;
+ enc._val3++;
+ writeString(5, 21, Common::String::format(
+ STRING["dialogs.encounter.give_up"].c_str(),
+ _bribeTypeStr.c_str()));
+ break;
+
+ case NOT_ENOUGH:
+ clearLines(20, 24);
+ writeString(14, 21, STRING["dialogs.encounter.not_enough"]);
+ delaySeconds(2);
+ break;
default:
break;
@@ -96,6 +119,15 @@ void Encounter::draw() {
writeString(enc._monsterList[i]._name);
}
}
+
+ if (_mode == NO_RESPONSE || _mode == NOT_ENOUGH) {
+ if (enc._val2) {
+ writeString(8, 23, STRING["dialogs.encounter.alignment_slips"]);
+ Sound::sound(SOUND_2);
+ }
+
+ _mode = ALIGNMENT_CHECK;
+ }
}
void Encounter::drawMonster(int monsterNum) {
@@ -140,6 +172,8 @@ void Encounter::timeout() {
}
bool Encounter::msgKeypress(const KeypressMessage &msg) {
+ const Maps::Map &map = *g_maps->_currentMap;
+
switch (_mode) {
case SURPRISED_MONSTERS:
if (msg.keycode == Common::KEYCODE_y) {
@@ -167,6 +201,21 @@ bool Encounter::msgKeypress(const KeypressMessage &msg) {
default:
break;
}
+ break;
+
+ case BRIBE:
+ if (msg.keycode == Common::KEYCODE_y) {
+ if (getRandomNumber(1, 100) > map[Maps::MAP_BRIBE_THRESHOLD]) {
+ _mode = NOT_ENOUGH;
+ redraw();
+ } else {
+ //xxxxxxxxxxx
+ }
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ _mode = ENCOUNTER_OPTIONS;
+ redraw();
+ }
+ break;
default:
break;
@@ -185,7 +234,36 @@ void Encounter::attack() {
}
void Encounter::bribe() {
+ const Game::Encounter &enc = g_globals->_encounters;
+
+ if (enc.checkSurroundParty()) {
+ if (!enc._val3)
+ updateAlignments();
+
+ _mode = NO_RESPONSE;
+ redraw();
+
+ } else if (getRandomNumber(1, 7) == 5 && !enc._val1) {
+ // Rare chance to abort combat immediately
+ encounterEnded();
+
+ } else {
+ _mode = BRIBE;
+
+ int val = getRandomNumber(1, 100);
+ if (val < 6) {
+ _bribeType = BRIBE_GEMS;
+ _bribeTypeStr = STRING["dialogs.encounter.gems"];
+ } else if (val < 16) {
+ _bribeType = BRIBE_FOOD;
+ _bribeTypeStr = STRING["dialogs.encounter.food"];
+ } else {
+ _bribeType = BRIBE_GOLD;
+ _bribeTypeStr = STRING["dialogs.encounter.gold"];
+ }
+ redraw();
+ }
}
void Encounter::retreat() {
@@ -246,6 +324,22 @@ void Encounter::flee() {
encounterEnded();
}
+void Encounter::updateAlignments() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ if (c._alignmentCtr) {
+ --c._alignmentCtr;
+ if (c._alignmentCtr == 0)
+ enc.changeCharAlignment(GOOD);
+ else if (c._alignmentCtr == 16)
+ enc.changeCharAlignment(NEUTRAL);
+ }
+ }
+}
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index f7d99e9fb27..4f6d1c63978 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -34,10 +34,14 @@ private:
enum Mode {
ALERT, SURPRISED_BY_MONSTERS, SURPRISED_MONSTERS,
ENCOUNTER_OPTIONS, NOWHERE_TO_RUN, SURRENDER_FAILED,
-
+ NO_RESPONSE, BRIBE, NOT_ENOUGH,
+ ALIGNMENT_CHECK,
BATTLE
};
Mode _mode = ALERT;
+ enum BribeType { BRIBE_GOLD, BRIBE_GEMS, BRIBE_FOOD };
+ BribeType _bribeType = BRIBE_GOLD;
+ Common::String _bribeTypeStr;
/**
* Draws a monster
@@ -53,6 +57,7 @@ private:
void retreat();
void surrender();
void flee();
+ void updateAlignments();
public:
Encounter();
virtual ~Encounter() {}
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 3ad4a706cdf..118b7ab5955 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -187,7 +187,7 @@ void Temple::restoreAlignment() {
if (subtractGold(_alignmentCost)) {
Character &c = *g_globals->_currCharacter;
c._alignment = c._alignmentInitial;
- c._v6f = ALIGNMENT_VALS[c._alignment];
+ c._alignmentCtr = ALIGNMENT_VALS[c._alignment];
redraw();
}
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
index e4408429450..52b03417707 100644
--- a/engines/mm/mm1/views_enh/locations/temple.cpp
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -191,7 +191,7 @@ void Temple::restoreAlignment() {
if (subtractGold(_alignmentCost)) {
Character &c = *g_globals->_currCharacter;
c._alignment = c._alignmentInitial;
- c._v6f = ALIGNMENT_VALS[c._alignment];
+ c._alignmentCtr = ALIGNMENT_VALS[c._alignment];
redraw();
}
Commit: 8ce5ba9a994eaf09fc53f0ba4fc42bb34ebd9279
https://github.com/scummvm/scummvm/commit/8ce5ba9a994eaf09fc53f0ba4fc42bb34ebd9279
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: Added more encounter view content
Changed paths:
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 5d9a70676c0..c1fd84bc916 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -104,6 +104,12 @@ void Encounter::draw() {
delaySeconds(2);
break;
+ case COMBAT:
+ clearLines(20, 24);
+ writeString(16, 21, STRING["dialogs.encounter.combat"]);
+ delaySeconds(2);
+ break;
+
default:
break;
}
@@ -120,7 +126,8 @@ void Encounter::draw() {
}
}
- if (_mode == NO_RESPONSE || _mode == NOT_ENOUGH) {
+ if (_mode == NO_RESPONSE || _mode == NOT_ENOUGH ||
+ _mode == COMBAT || _mode == SURPRISED_BY_MONSTERS) {
if (enc._val2) {
writeString(8, 23, STRING["dialogs.encounter.alignment_slips"]);
Sound::sound(SOUND_2);
@@ -159,8 +166,7 @@ void Encounter::timeout() {
}
break;
- case NOWHERE_TO_RUN:
- case SURRENDER_FAILED:
+ case ALIGNMENT_CHECK:
_mode = BATTLE;
break;
@@ -209,7 +215,19 @@ bool Encounter::msgKeypress(const KeypressMessage &msg) {
_mode = NOT_ENOUGH;
redraw();
} else {
- //xxxxxxxxxxx
+ switch (_bribeType) {
+ case BRIBE_GOLD:
+ g_globals->_party.clearPartyGold();
+ break;
+ case BRIBE_GEMS:
+ g_globals->_party.clearPartyGems();
+ break;
+ case BRIBE_FOOD:
+ g_globals->_party.clearPartyFood();
+ break;
+ }
+
+ encounterEnded();
}
} else if (msg.keycode == Common::KEYCODE_n) {
_mode = ENCOUNTER_OPTIONS;
@@ -230,7 +248,15 @@ void Encounter::encounterEnded() {
}
void Encounter::attack() {
+ const Game::Encounter &enc = g_globals->_encounters;
+
+ if (!enc.checkSurroundParty() || !enc.checkSurroundParty() ||
+ !enc.checkSurroundParty()) {
+ increaseAlignments();
+ }
+ _mode = COMBAT;
+ redraw();
}
void Encounter::bribe() {
@@ -238,7 +264,7 @@ void Encounter::bribe() {
if (enc.checkSurroundParty()) {
if (!enc._val3)
- updateAlignments();
+ decreaseAlignments();
_mode = NO_RESPONSE;
redraw();
@@ -324,7 +350,7 @@ void Encounter::flee() {
encounterEnded();
}
-void Encounter::updateAlignments() {
+void Encounter::decreaseAlignments() {
Game::Encounter &enc = g_globals->_encounters;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
@@ -341,6 +367,23 @@ void Encounter::updateAlignments() {
}
}
+void Encounter::increaseAlignments() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ if (c._alignmentCtr != 32) {
+ ++c._alignmentCtr;
+ if (c._alignmentCtr == 32)
+ enc.changeCharAlignment(EVIL);
+ else if (c._alignmentCtr == 16)
+ enc.changeCharAlignment(NEUTRAL);
+ }
+ }
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index 4f6d1c63978..719bdea7945 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -34,7 +34,7 @@ private:
enum Mode {
ALERT, SURPRISED_BY_MONSTERS, SURPRISED_MONSTERS,
ENCOUNTER_OPTIONS, NOWHERE_TO_RUN, SURRENDER_FAILED,
- NO_RESPONSE, BRIBE, NOT_ENOUGH,
+ NO_RESPONSE, BRIBE, NOT_ENOUGH, COMBAT,
ALIGNMENT_CHECK,
BATTLE
};
@@ -57,7 +57,8 @@ private:
void retreat();
void surrender();
void flee();
- void updateAlignments();
+ void decreaseAlignments();
+ void increaseAlignments();
public:
Encounter();
virtual ~Encounter() {}
Commit: 31ded9b30f98e8472a0342ca0d8b04ff0f132611
https://github.com/scummvm/scummvm/commit/31ded9b30f98e8472a0342ca0d8b04ff0f132611
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: Field renamings for encounter manager
Changed paths:
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 7e74d3a2cf1..efa5dc4d61d 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -33,14 +33,15 @@ namespace Game {
void Encounter::execute() {
Maps::Map &map = *g_maps->_currentMap;
int comp, maxRand, maxVal, monsterCount;
- _val1 = _val2 = _val3 = 0;
+ _bribeFleeCtr = _bribeAlignmentCtr = 0;
+ _alignmentsChanged = 0;
if (!_flag) {
- _levelIndex = _val5 = 0;
+ _levelIndex = _monsterIndex = 0;
}
_totalLevels = _highestLevel = 0;
- _val6 = _val8 = _val9 = _fleeThreshold = 0;
+ _levelOffset = _monsterImgNum = _val9 = _fleeThreshold = 0;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
const Character &c = g_globals->_party[i];
@@ -59,7 +60,7 @@ void Encounter::execute() {
while (firstLoop || _levelIndex < _totalLevels) {
randomAdjust();
- maxRand = _val6 + _highestLevel;
+ maxRand = _levelOffset + _highestLevel;
if (maxRand >= 2) {
int highestRand = map[33];
maxRand = MIN(maxRand, highestRand);
@@ -73,32 +74,32 @@ void Encounter::execute() {
comp = MIN(maxVal, 10);
}
- assert(_val5 < 15);
- _arr1[_val5] = comp;
+ assert(_monsterIndex < 15);
+ _arr1[_monsterIndex] = comp;
_val11 = comp;
_levelIndex += comp;
_randVal = g_engine->getRandomNumber(1, 16);
- _arr2[_val5] = _randVal;
- _val5 = (_val5 + 1) & 0xff;
+ _arr2[_monsterIndex] = _randVal;
+ _monsterIndex = (_monsterIndex + 1) & 0xff;
- if (_val5 < 15) {
- if (_val5 >= map[34])
+ if (_monsterIndex < 15) {
+ if (_monsterIndex >= map[34])
goto exit_loop;
monsterCount = getMonsterCount();
maxVal = g_engine->getRandomNumber(1, monsterCount);
for (int i = 0; i < maxVal; ++i) {
- assert(_val5 > 0);
- _arr1[_val5] = _arr1[_val5 - 1];
- _levelIndex += _arr1[_val5];
- _arr2[_val5] = _arr2[_val5 - 1];
+ assert(_monsterIndex > 0);
+ _arr1[_monsterIndex] = _arr1[_monsterIndex - 1];
+ _levelIndex += _arr1[_monsterIndex];
+ _arr2[_monsterIndex] = _arr2[_monsterIndex - 1];
- if (++_val5 >= 15)
+ if (++_monsterIndex >= 15)
goto exit_loop;
- if (_val5 >= map[34])
+ if (_monsterIndex >= map[34])
goto exit_loop;
}
} else {
@@ -109,7 +110,7 @@ void Encounter::execute() {
exit_loop:
_monsterList.clear();
- for (int i = 0; i < _val5; ++i) {
+ for (int i = 0; i < _monsterIndex; ++i) {
maxVal = (_arr1[i] - 1) * 16 + _arr2[i];
if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
_arr1[i] = 10;
@@ -125,7 +126,7 @@ exit_loop:
if (_val11 > _val9) {
_val9 = _val11;
_fleeThreshold = mons._counts[1];
- _val8 = mons._counts[16];
+ _monsterImgNum = mons._counts[16];
}
}
@@ -134,17 +135,17 @@ exit_loop:
void Encounter::randomAdjust() {
int rval = g_engine->getRandomNumber(1, 100);
- _val6 = 0;
+ _levelOffset = 0;
if (rval < 51) {
} else if (rval < 71)
- _val6 += 1;
+ _levelOffset += 1;
else if (rval < 86)
- _val6 += 2;
+ _levelOffset += 2;
else if (rval < 96)
- _val6 += 3;
+ _levelOffset += 3;
else
- _val6 += 4;
+ _levelOffset += 4;
}
const Monster *Encounter::getMonster() {
@@ -164,7 +165,7 @@ bool Encounter::checkSurroundParty() const {
void Encounter::changeCharAlignment(Alignment align) {
if (g_globals->_currCharacter->_alignment != align) {
g_globals->_currCharacter->_alignment = align;
- ++_val2;
+ ++_alignmentsChanged;
}
}
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index c1448c3dc01..757277b4c6d 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -37,7 +37,7 @@ enum EncounterType {
struct Encounter {
private:
bool _flag = false;
- int _levelIndex = 0, _val6 = 0;
+ int _levelIndex = 0, _levelOffset = 0;
int _val9 = 0;
int _val11 = 0;
int _totalLevels = 0, _highestLevel = 0;
@@ -49,8 +49,10 @@ private:
byte getMonsterCount();
public:
Common::Array<Monster> _monsterList;
- int _val1 = 0, _val2 = 0;
- int _val3 = 0, _val5 = 0, _val8 = 0;
+ int _bribeAlignmentCtr = 0, _bribeFleeCtr = 0;
+ int _alignmentsChanged = 0;
+ int _monsterImgNum = 0;
+ int _monsterIndex = 0;
EncounterType _encounterFlag = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
public:
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index c1fd84bc916..750efe9111c 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -91,8 +91,8 @@ void Encounter::draw() {
break;
case BRIBE:
- enc._val1++;
- enc._val3++;
+ enc._bribeFleeCtr++;
+ enc._bribeAlignmentCtr++;
writeString(5, 21, Common::String::format(
STRING["dialogs.encounter.give_up"].c_str(),
_bribeTypeStr.c_str()));
@@ -116,7 +116,7 @@ void Encounter::draw() {
if (_mode != ALERT) {
// Display the monster
- drawMonster(enc._val8);
+ drawMonster(enc._monsterImgNum);
// Write the monster list
for (uint i = 0; i < enc._monsterList.size(); ++i) {
@@ -128,7 +128,7 @@ void Encounter::draw() {
if (_mode == NO_RESPONSE || _mode == NOT_ENOUGH ||
_mode == COMBAT || _mode == SURPRISED_BY_MONSTERS) {
- if (enc._val2) {
+ if (enc._alignmentsChanged) {
writeString(8, 23, STRING["dialogs.encounter.alignment_slips"]);
Sound::sound(SOUND_2);
}
@@ -263,13 +263,13 @@ void Encounter::bribe() {
const Game::Encounter &enc = g_globals->_encounters;
if (enc.checkSurroundParty()) {
- if (!enc._val3)
+ if (!enc._bribeAlignmentCtr)
decreaseAlignments();
_mode = NO_RESPONSE;
redraw();
- } else if (getRandomNumber(1, 7) == 5 && !enc._val1) {
+ } else if (getRandomNumber(1, 7) == 5 && !enc._bribeFleeCtr) {
// Rare chance to abort combat immediately
encounterEnded();
@@ -301,7 +301,7 @@ void Encounter::retreat() {
} else if (val > Maps::MAP_FLEE_THRESHOLD) {
_mode = NOWHERE_TO_RUN;
redraw();
- } else if (enc._val5 < (int)g_globals->_party.size() || !enc.checkSurroundParty()) {
+ } else if (enc._monsterIndex < (int)g_globals->_party.size() || !enc.checkSurroundParty()) {
flee();
}
}
Commit: fb04ecadb96a801c67558ab606ce7b6c7ef2b43a
https://github.com/scummvm/scummvm/commit/fb04ecadb96a801c67558ab606ce7b6c7ef2b43a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:09+01:00
Commit Message:
MM: MM1: Fix remaining _val11 misunderstandings in encounter setup
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 53520cd0ea4..52c4feb56c2 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -40,8 +40,10 @@ bool Monsters::load() {
mon._name = Common::String(line.c_str() + 1, line.c_str() + 15);
line = Common::String(line.c_str() + 17);
- for (int i = 0; i < 17; ++i)
- mon._counts[i] = getNextValue(line);
+ mon._count = getNextValue(line);
+
+ for (int i = 0; i < 16; ++i)
+ mon._unk[i] = getNextValue(line);
}
return true;
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 1f4ae134ba0..d3c9a2a97e4 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -33,7 +33,8 @@ namespace MM1 {
struct Monster {
Common::String _name; // char _name[15];
- byte _counts[17];
+ byte _count;
+ byte _unk[16];
};
class Monsters {
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index efa5dc4d61d..407857786e5 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -32,7 +32,8 @@ namespace Game {
void Encounter::execute() {
Maps::Map &map = *g_maps->_currentMap;
- int comp, maxRand, maxVal, monsterCount;
+ int comp, maxRand, maxVal;
+ const Monster *monsterP;
_bribeFleeCtr = _bribeAlignmentCtr = 0;
_alignmentsChanged = 0;
@@ -76,19 +77,19 @@ void Encounter::execute() {
assert(_monsterIndex < 15);
_arr1[_monsterIndex] = comp;
- _val11 = comp;
+ _monsterNum16 = comp;
_levelIndex += comp;
- _randVal = g_engine->getRandomNumber(1, 16);
- _arr2[_monsterIndex] = _randVal;
+ _monsterNum = g_engine->getRandomNumber(1, 16);
+ _arr2[_monsterIndex] = _monsterNum;
_monsterIndex = (_monsterIndex + 1) & 0xff;
if (_monsterIndex < 15) {
if (_monsterIndex >= map[34])
goto exit_loop;
- monsterCount = getMonsterCount();
- maxVal = g_engine->getRandomNumber(1, monsterCount);
+ monsterP = getMonster();
+ maxVal = g_engine->getRandomNumber(1, monsterP->_count);
for (int i = 0; i < maxVal; ++i) {
assert(_monsterIndex > 0);
@@ -118,15 +119,14 @@ exit_loop:
}
// Add monster details to list
- _val11 = _arr1[i];
- assert(_val11 == 1);
+ _monsterNum16 = _arr1[i];
const Monster &mons = g_globals->_monsters[_arr2[i]];
_monsterList.push_back(mons);
- if (_val11 > _val9) {
- _val9 = _val11;
- _fleeThreshold = mons._counts[1];
- _monsterImgNum = mons._counts[16];
+ if (_monsterNum16 > _val9) {
+ _val9 = _monsterNum16;
+ _fleeThreshold = mons._unk[0];
+ _monsterImgNum = mons._unk[15];
}
}
@@ -149,13 +149,8 @@ void Encounter::randomAdjust() {
}
const Monster *Encounter::getMonster() {
- assert(_randVal > 0);
- return &g_globals->_monsters[_randVal];
-}
-
-byte Encounter::getMonsterCount() {
- assert(_val11 >= 1 && _val11 <= 8);
- return getMonster()->_counts[(_val11 - 1) * 2];
+ assert(_monsterNum > 0 && _monsterNum16 > 0);
+ return &g_globals->_monsters[_monsterNum + ((_monsterNum16 - 1) * 16)];
}
bool Encounter::checkSurroundParty() const {
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 757277b4c6d..ae94407a734 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -39,14 +39,13 @@ private:
bool _flag = false;
int _levelIndex = 0, _levelOffset = 0;
int _val9 = 0;
- int _val11 = 0;
+ int _monsterNum16 = 0;
int _totalLevels = 0, _highestLevel = 0;
- int _randVal = 0;
+ int _monsterNum = 0;
byte _arr1[15], _arr2[15];
void randomAdjust();
const Monster *getMonster();
- byte getMonsterCount();
public:
Common::Array<Monster> _monsterList;
int _bribeAlignmentCtr = 0, _bribeFleeCtr = 0;
Commit: 0c5831360891cbe81d2a8b7c3c3fdab8e97bb118
https://github.com/scummvm/scummvm/commit/0c5831360891cbe81d2a8b7c3c3fdab8e97bb118
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Fixed for encounter retreat option
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9953ccfe9cf..178bf04797f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -275,6 +275,8 @@
options1: "OPTIONS: 'A' ATTACK 'R' RETREAT"
options2: "'B' BRIBE 'S' SURRENDER"
surrender_failed: "THE MONSTERS DON'T TAKE PRISONERS!"
+ nowhere_to_run: "NOWHERE TO RUN"
+ surround: "THE MONSTERS SURROUND YOU!"
no_response: "NO RESPONSE"
give_up: "GIVE UP ALL YOUR %s (Y/N)?"
gems: "GEMS"
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 750efe9111c..445c15ec4a1 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -67,8 +67,8 @@ void Encounter::draw() {
// Write the encounter options
clearLines(20, 24);
- writeString(0, 21, STRING["dialogs.encounter.option1"]);
- writeString(10, 22, STRING["dialogs.encounter.option2"]);
+ writeString(0, 21, STRING["dialogs.encounter.options1"]);
+ writeString(10, 22, STRING["dialogs.encounter.options2"]);
break;
}
@@ -78,6 +78,12 @@ void Encounter::draw() {
delaySeconds(2);
break;
+ case SURROUNDED:
+ clearLines(20, 24);
+ writeString(5, 21, STRING["dialogs.encounter.surround"]);
+ delaySeconds(2);
+ break;
+
case SURRENDER_FAILED:
clearLines(20, 24);
writeString(2, 21, STRING["dialogs.encounter.surrender_failed"]);
@@ -126,8 +132,9 @@ void Encounter::draw() {
}
}
- if (_mode == NO_RESPONSE || _mode == NOT_ENOUGH ||
- _mode == COMBAT || _mode == SURPRISED_BY_MONSTERS) {
+ if (_mode == NO_RESPONSE || _mode == SURROUNDED ||
+ _mode == NOT_ENOUGH || _mode == COMBAT ||
+ _mode == SURPRISED_BY_MONSTERS) {
if (enc._alignmentsChanged) {
writeString(8, 23, STRING["dialogs.encounter.alignment_slips"]);
Sound::sound(SOUND_2);
@@ -293,16 +300,24 @@ void Encounter::bribe() {
}
void Encounter::retreat() {
+ const Maps::Map &map = *g_maps->_currentMap;
const Game::Encounter &enc = g_globals->_encounters;
int val = getRandomNumber(1, 110);
if (val >= 100) {
+ // 9% chance of simply fleeing
flee();
- } else if (val > Maps::MAP_FLEE_THRESHOLD) {
+ } else if (val > map[Maps::MAP_FLEE_THRESHOLD]) {
+ // Nowhere to run depending on the map
_mode = NOWHERE_TO_RUN;
redraw();
- } else if (enc._monsterIndex < (int)g_globals->_party.size() || !enc.checkSurroundParty()) {
+ } else if (enc._monsterList.size() < (int)g_globals->_party.size() || !enc.checkSurroundParty()) {
+ // Only allow fleeing if the number of monsters
+ // are less than the size of the party
flee();
+ } else {
+ _mode = SURROUNDED;
+ redraw();
}
}
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index 719bdea7945..1ca429a9d58 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -33,10 +33,9 @@ class Encounter : public TextView {
private:
enum Mode {
ALERT, SURPRISED_BY_MONSTERS, SURPRISED_MONSTERS,
- ENCOUNTER_OPTIONS, NOWHERE_TO_RUN, SURRENDER_FAILED,
- NO_RESPONSE, BRIBE, NOT_ENOUGH, COMBAT,
- ALIGNMENT_CHECK,
- BATTLE
+ ENCOUNTER_OPTIONS, NOWHERE_TO_RUN, SURROUNDED,
+ SURRENDER_FAILED, NO_RESPONSE, BRIBE, NOT_ENOUGH,
+ COMBAT, ALIGNMENT_CHECK, BATTLE
};
Mode _mode = ALERT;
enum BribeType { BRIBE_GOLD, BRIBE_GEMS, BRIBE_FOOD };
Commit: 33af429c517ec459de91904bc7f9cecce5eda754
https://github.com/scummvm/scummvm/commit/33af429c517ec459de91904bc7f9cecce5eda754
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Beginnings of combat view
Changed paths:
A engines/mm/mm1/views/combat.cpp
A engines/mm/mm1/views/combat.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/data/party.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 178bf04797f..3dcb02f5132 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -284,6 +284,7 @@
gold: "GOLD"
not_enough: "NOT ENOUGH"
alignment_slips: "*** ALIGNMENT SLIPS ***"
+ combat: "COMBAT!"
enhdialogs:
character:
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 52c4feb56c2..9809b245e7e 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -41,8 +41,11 @@ bool Monsters::load() {
line = Common::String(line.c_str() + 17);
mon._count = getNextValue(line);
+ mon._field10 = getNextValue(line);
+ mon._field11 = getNextValue(line);
+ mon._field12 = getNextValue(line);
- for (int i = 0; i < 16; ++i)
+ for (int i = 0; i < 13; ++i)
mon._unk[i] = getNextValue(line);
}
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index d3c9a2a97e4..aca4e04105a 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -34,7 +34,11 @@ namespace MM1 {
struct Monster {
Common::String _name; // char _name[15];
byte _count;
- byte _unk[16];
+ byte _field10;
+ byte _field11;
+ byte _field12;
+ byte _unk[12];
+ byte _field1f;
};
class Monsters {
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index c1227030f4f..1bc89b1fe74 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -28,6 +28,8 @@
namespace MM {
namespace MM1 {
+#define MAX_PARTY_SIZE 6
+
struct Party : public Common::Array<Character> {
/**
* Share food, gold, gems between entire party
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 407857786e5..5c64f9c10e5 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -75,7 +75,7 @@ void Encounter::execute() {
comp = MIN(maxVal, 10);
}
- assert(_monsterIndex < 15);
+ assert(_monsterIndex < MAX_COMBAT_MONSTERS);
_arr1[_monsterIndex] = comp;
_monsterNum16 = comp;
_levelIndex += comp;
@@ -84,7 +84,7 @@ void Encounter::execute() {
_arr2[_monsterIndex] = _monsterNum;
_monsterIndex = (_monsterIndex + 1) & 0xff;
- if (_monsterIndex < 15) {
+ if (_monsterIndex < MAX_COMBAT_MONSTERS) {
if (_monsterIndex >= map[34])
goto exit_loop;
@@ -97,7 +97,7 @@ void Encounter::execute() {
_levelIndex += _arr1[_monsterIndex];
_arr2[_monsterIndex] = _arr2[_monsterIndex - 1];
- if (++_monsterIndex >= 15)
+ if (++_monsterIndex >= MAX_COMBAT_MONSTERS)
goto exit_loop;
if (_monsterIndex >= map[34])
@@ -115,7 +115,7 @@ exit_loop:
maxVal = (_arr1[i] - 1) * 16 + _arr2[i];
if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
_arr1[i] = 10;
- _arr2[i] = g_engine->getRandomNumber(1, 15);
+ _arr2[i] = g_engine->getRandomNumber(1, MAX_COMBAT_MONSTERS);
}
// Add monster details to list
@@ -125,8 +125,8 @@ exit_loop:
if (_monsterNum16 > _val9) {
_val9 = _monsterNum16;
- _fleeThreshold = mons._unk[0];
- _monsterImgNum = mons._unk[15];
+ _fleeThreshold = mons._field10;
+ _monsterImgNum = mons._field1f;
}
}
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index ae94407a734..ea6717db3ba 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -30,6 +30,8 @@ namespace MM {
namespace MM1 {
namespace Game {
+#define MAX_COMBAT_MONSTERS 15
+
enum EncounterType {
FORCE_SURPRISED = -1, NORMAL_SURPRISED = 0, NORMAL_ENCOUNTER = 1
};
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
new file mode 100644
index 00000000000..6f53f44fd31
--- /dev/null
+++ b/engines/mm/mm1/views/combat.cpp
@@ -0,0 +1,107 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/combat.h"
+#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Combat::Combat() : TextView("Combat") {
+}
+
+bool Combat::msgFocus(const FocusMessage &msg) {
+ Game::Encounter &enc = g_globals->_encounters;
+ _mode = BATTLE;
+
+ // Clear combat data
+ clear();
+
+ _monstersCount = enc._monsterList.size();
+ _party.clear();
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ _party.push_back(&g_globals->_party[i]);
+
+ loadArrays();
+
+ return true;
+}
+
+void Combat::clear() {
+ Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_arr4[0], &_arr4[MAX_PARTY_SIZE], 0);
+ _val1 = _val8 = _val9 = _val10 = 0;
+ _monsterP = nullptr;
+ _monsterIndex = 0;
+ // TODO: clear everything
+}
+
+void Combat::loadArrays() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ for (uint i = 0; i < enc._monsterList.size(); ++i) {
+ Monster &mon = enc._monsterList[i];
+ int val = getRandomNumber(1, 8);
+
+ mon._field11 += val;
+ _arr1[i] = mon._field11;
+ _arr2[i] = mon._field12;
+
+ monsterIndexOf();
+ }
+}
+
+void Combat::monsterIndexOf() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ _monsterIndex = MAX_COMBAT_MONSTERS;
+ for (uint i = 0; i < enc._monsterList.size(); ++i) {
+ if (_monsterP == &enc._monsterList[i]) {
+ _monsterIndex = i;
+ break;
+ }
+ }
+}
+
+void Combat::draw() {
+ //Game::Encounter &enc = g_globals->_encounters;
+
+ clearSurface();
+ writeString(10, 10, "TODO: COMBAT VIEW");
+}
+
+void Combat::timeout() {
+ redraw();
+}
+
+bool Combat::msgKeypress(const KeypressMessage &msg) {
+ return true;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
new file mode 100644
index 00000000000..4c8395cae7b
--- /dev/null
+++ b/engines/mm/mm1/views/combat.h
@@ -0,0 +1,83 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_COMBAT_H
+#define MM1_VIEWS_COMBAT_H
+
+#include "mm/mm1/events.h"
+#include "mm/mm1/data/party.h"
+#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Combat : public TextView {
+private:
+ enum Mode {
+ BATTLE
+ };
+ Mode _mode = BATTLE;
+ int _monstersCount = 0;
+ Common::Array<Character *> _party;
+ Monster *_monsterP;
+ byte _arr1[MAX_COMBAT_MONSTERS];
+ byte _arr2[MAX_COMBAT_MONSTERS];
+ byte _arr3[MAX_COMBAT_MONSTERS];
+ byte _arr4[MAX_PARTY_SIZE];
+ int _val1, _val8, _val9, _val10;
+ int _monsterIndex;
+
+ void clear();
+ void loadArrays();
+ void monsterIndexOf();
+public:
+ Combat();
+ virtual ~Combat() {}
+
+ /**
+ * Called when the view is focused
+ */
+ bool msgFocus(const FocusMessage &msg) override;
+
+ /**
+ * Draw the Combat details overlayed on
+ * the existing game screen
+ */
+ void draw() override;
+
+ /**
+ * Handles delay timeouts
+ */
+ void timeout() override;
+
+ /**
+ * Handles keypresses
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 2ee43d9ec77..11ef9de0947 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -24,6 +24,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/are_you_ready.h"
+#include "mm/mm1/views/combat.h"
#include "mm/mm1/views/create_characters.h"
#include "mm/mm1/views/encounter.h"
#include "mm/mm1/views/game.h"
@@ -57,6 +58,7 @@ namespace Views {
struct Dialogs {
private:
Views::AreYouReady _areYouReady;
+ Views::Combat _combat;
Views::CreateCharacters _createCharacters;
Views::Encounter _encounter;
Views::Game _game;
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 445c15ec4a1..8355f3cff0e 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -140,7 +140,7 @@ void Encounter::draw() {
Sound::sound(SOUND_2);
}
- _mode = ALIGNMENT_CHECK;
+ _mode = BATTLE;
}
}
@@ -173,8 +173,9 @@ void Encounter::timeout() {
}
break;
- case ALIGNMENT_CHECK:
- _mode = BATTLE;
+ case BATTLE:
+ // Switch to combat view
+ replaceView("Combat");
break;
default:
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index 1ca429a9d58..d89027923ea 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -35,7 +35,7 @@ private:
ALERT, SURPRISED_BY_MONSTERS, SURPRISED_MONSTERS,
ENCOUNTER_OPTIONS, NOWHERE_TO_RUN, SURROUNDED,
SURRENDER_FAILED, NO_RESPONSE, BRIBE, NOT_ENOUGH,
- COMBAT, ALIGNMENT_CHECK, BATTLE
+ COMBAT, BATTLE
};
Mode _mode = ALERT;
enum BribeType { BRIBE_GOLD, BRIBE_GEMS, BRIBE_FOOD };
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 297d9a299a3..402768ffc0d 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -58,6 +58,7 @@ MODULE_OBJS := \
mm1/views/character_info.o \
mm1/views/character_manage.o \
mm1/views/characters.o \
+ mm1/views/combat.o \
mm1/views/create_characters.o \
mm1/views/encounter.o \
mm1/views/game.o \
Commit: ad5c7997f7f006e86b9260a9db01134fde49698b
https://github.com/scummvm/scummvm/commit/ad5c7997f7f006e86b9260a9db01134fde49698b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Move beginnings of combat data into separate class
This will save time later on for the Enhanced version,
which will need the same game logic, and just a different
view.
Changed paths:
A engines/mm/mm1/game/combat.cpp
A engines/mm/mm1/game/combat.h
A engines/mm/mm1/game/game_logic.cpp
A engines/mm/mm1/game/game_logic.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3dcb02f5132..c921e70fe30 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -285,6 +285,9 @@
not_enough: "NOT ENOUGH"
alignment_slips: "*** ALIGNMENT SLIPS ***"
combat: "COMBAT!"
+ combat:
+ attack: "'A' ATTACK(A)"
+ fight: "'F' FIGHT(+)"
enhdialogs:
character:
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
new file mode 100644
index 00000000000..381ca3f9085
--- /dev/null
+++ b/engines/mm/mm1/game/combat.cpp
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/game/combat.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+void Combat::clear() {
+ Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_canAttack[0], &_canAttack[6], false);
+ _val1 = _val8 = _val9 = _val10 = 0;
+ _monsterP = nullptr;
+ _monsterIndex = 0;
+ // TODO: clear everything
+}
+
+
+void Combat::loadArrays() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ for (uint i = 0; i < enc._monsterList.size(); ++i) {
+ Monster &mon = enc._monsterList[i];
+ int val = getRandomNumber(1, 8);
+
+ mon._field11 += val;
+ _arr1[i] = mon._field11;
+ _arr2[i] = mon._field12;
+
+ monsterIndexOf();
+ }
+}
+
+void Combat::monsterIndexOf() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ _monsterIndex = MAX_COMBAT_MONSTERS;
+ for (uint i = 0; i < enc._monsterList.size(); ++i) {
+ if (_monsterP == &enc._monsterList[i]) {
+ _monsterIndex = i;
+ break;
+ }
+ }
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
new file mode 100644
index 00000000000..c7b4568411c
--- /dev/null
+++ b/engines/mm/mm1/game/combat.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_COMBAT_H
+#define MM1_GAME_COMBAT_H
+
+#include "common/array.h"
+#include "mm/mm1/data/character.h"
+#include "mm/mm1/data/party.h"
+#include "mm/mm1/game/game_logic.h"
+#include "mm/mm1/game/encounter.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+class Combat : public GameLogic {
+protected:
+ int _monstersCount = 0;
+ Common::Array<Character *> _party;
+ Monster *_monsterP;
+ byte _arr1[MAX_COMBAT_MONSTERS];
+ byte _arr2[MAX_COMBAT_MONSTERS];
+ byte _arr3[MAX_COMBAT_MONSTERS];
+ bool _canAttack[MAX_PARTY_SIZE];
+ int _val1, _val8, _val9, _val10;
+ int _monsterIndex;
+
+ Combat() { clear(); }
+
+ /**
+ * Clear all the combat variables
+ */
+ void clear();
+
+ void loadArrays();
+ void monsterIndexOf();
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 5c64f9c10e5..40cbba9c1e4 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -65,7 +65,7 @@ void Encounter::execute() {
if (maxRand >= 2) {
int highestRand = map[33];
maxRand = MIN(maxRand, highestRand);
- comp = g_engine->getRandomNumber(1, maxRand);
+ comp = getRandomNumber(1, maxRand);
} else {
comp = 1;
}
@@ -80,7 +80,7 @@ void Encounter::execute() {
_monsterNum16 = comp;
_levelIndex += comp;
- _monsterNum = g_engine->getRandomNumber(1, 16);
+ _monsterNum = getRandomNumber(1, 16);
_arr2[_monsterIndex] = _monsterNum;
_monsterIndex = (_monsterIndex + 1) & 0xff;
@@ -89,7 +89,7 @@ void Encounter::execute() {
goto exit_loop;
monsterP = getMonster();
- maxVal = g_engine->getRandomNumber(1, monsterP->_count);
+ maxVal = getRandomNumber(1, monsterP->_count);
for (int i = 0; i < maxVal; ++i) {
assert(_monsterIndex > 0);
@@ -115,7 +115,7 @@ exit_loop:
maxVal = (_arr1[i] - 1) * 16 + _arr2[i];
if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
_arr1[i] = 10;
- _arr2[i] = g_engine->getRandomNumber(1, MAX_COMBAT_MONSTERS);
+ _arr2[i] = getRandomNumber(1, MAX_COMBAT_MONSTERS);
}
// Add monster details to list
@@ -134,7 +134,7 @@ exit_loop:
}
void Encounter::randomAdjust() {
- int rval = g_engine->getRandomNumber(1, 100);
+ int rval = getRandomNumber(1, 100);
_levelOffset = 0;
if (rval < 51) {
@@ -154,7 +154,7 @@ const Monster *Encounter::getMonster() {
}
bool Encounter::checkSurroundParty() const {
- return g_engine->getRandomNumber(1, 100) > _fleeThreshold;
+ return getRandomNumber(1, 100) > _fleeThreshold;
}
void Encounter::changeCharAlignment(Alignment align) {
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index ea6717db3ba..a6eb9f1d28e 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -25,6 +25,7 @@
#include "common/array.h"
#include "mm/mm1/data/character.h"
#include "mm/mm1/data/monsters.h"
+#include "mm/mm1/game/game_logic.h"
namespace MM {
namespace MM1 {
@@ -36,7 +37,7 @@ enum EncounterType {
FORCE_SURPRISED = -1, NORMAL_SURPRISED = 0, NORMAL_ENCOUNTER = 1
};
-struct Encounter {
+class Encounter : public GameLogic {
private:
bool _flag = false;
int _levelIndex = 0, _levelOffset = 0;
diff --git a/engines/mm/mm1/game/game_logic.cpp b/engines/mm/mm1/game/game_logic.cpp
new file mode 100644
index 00000000000..97a83d883be
--- /dev/null
+++ b/engines/mm/mm1/game/game_logic.cpp
@@ -0,0 +1,39 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/game/game_logic.h"
+#include "mm/mm1/mm1.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+int GameLogic::getRandomNumber(int minNumber, int maxNumber) {
+ return g_engine->getRandomNumber(maxNumber - minNumber + 1) + minNumber;
+}
+
+int GameLogic::getRandomNumber(int maxNumber) {
+ return g_engine->getRandomNumber(maxNumber);
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/game_logic.h b/engines/mm/mm1/game/game_logic.h
new file mode 100644
index 00000000000..275a9352592
--- /dev/null
+++ b/engines/mm/mm1/game/game_logic.h
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_GAME_LOGIC_H
+#define MM1_GAME_GAME_LOGIC_H
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+class GameLogic {
+public:
+ /**
+ * Returns a random number
+ */
+ static int getRandomNumber(int minNumber, int maxNumber);
+ static int getRandomNumber(int maxNumber);
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 6f53f44fd31..8b227f7c5b3 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -49,44 +49,6 @@ bool Combat::msgFocus(const FocusMessage &msg) {
return true;
}
-void Combat::clear() {
- Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_arr4[0], &_arr4[MAX_PARTY_SIZE], 0);
- _val1 = _val8 = _val9 = _val10 = 0;
- _monsterP = nullptr;
- _monsterIndex = 0;
- // TODO: clear everything
-}
-
-void Combat::loadArrays() {
- Game::Encounter &enc = g_globals->_encounters;
-
- for (uint i = 0; i < enc._monsterList.size(); ++i) {
- Monster &mon = enc._monsterList[i];
- int val = getRandomNumber(1, 8);
-
- mon._field11 += val;
- _arr1[i] = mon._field11;
- _arr2[i] = mon._field12;
-
- monsterIndexOf();
- }
-}
-
-void Combat::monsterIndexOf() {
- Game::Encounter &enc = g_globals->_encounters;
-
- _monsterIndex = MAX_COMBAT_MONSTERS;
- for (uint i = 0; i < enc._monsterList.size(); ++i) {
- if (_monsterP == &enc._monsterList[i]) {
- _monsterIndex = i;
- break;
- }
- }
-}
-
void Combat::draw() {
//Game::Encounter &enc = g_globals->_encounters;
@@ -102,6 +64,12 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
return true;
}
+void Combat::writeAttackOptions() {
+ writeString(16, 20, STRING["dialogs.combat.attack"]);
+ writeString(16, 21, STRING["dialogs.combat.fight"]);
+}
+
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 4c8395cae7b..04fff81b192 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -22,34 +22,21 @@
#ifndef MM1_VIEWS_COMBAT_H
#define MM1_VIEWS_COMBAT_H
-#include "mm/mm1/events.h"
-#include "mm/mm1/data/party.h"
-#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/game/combat.h"
#include "mm/mm1/views/text_view.h"
namespace MM {
namespace MM1 {
namespace Views {
-class Combat : public TextView {
+class Combat : public TextView, public Game::Combat {
private:
enum Mode {
BATTLE
};
Mode _mode = BATTLE;
- int _monstersCount = 0;
- Common::Array<Character *> _party;
- Monster *_monsterP;
- byte _arr1[MAX_COMBAT_MONSTERS];
- byte _arr2[MAX_COMBAT_MONSTERS];
- byte _arr3[MAX_COMBAT_MONSTERS];
- byte _arr4[MAX_PARTY_SIZE];
- int _val1, _val8, _val9, _val10;
- int _monsterIndex;
- void clear();
- void loadArrays();
- void monsterIndexOf();
+ void writeAttackOptions();
public:
Combat();
virtual ~Combat() {}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 402768ffc0d..7e18616a745 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -22,6 +22,8 @@ MODULE_OBJS := \
mm1/data/party.o \
mm1/data/roster.o \
mm1/data/spells.o \
+ mm1/game/game_logic.o \
+ mm1/game/combat.o \
mm1/game/encounter.o \
mm1/game/rest.o \
mm1/game/search.o \
Commit: 8ec640a2dc70fd3aae9e20075355ebce9e9d16b3
https://github.com/scummvm/scummvm/commit/8ec640a2dc70fd3aae9e20075355ebce9e9d16b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Implementing display of combat options
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
engines/mm/utils/bitmap_font.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c921e70fe30..30fc9a42311 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -286,8 +286,13 @@
alignment_slips: "*** ALIGNMENT SLIPS ***"
combat: "COMBAT!"
combat:
+ options_for: "OPTIONS FOR: "
attack: "'A' ATTACK(A)"
+ cast: "'C' CAST"
fight: "'F' FIGHT(+)"
+ shoot: "'S' SHOOT"
+ exchange_use: "'E' EXCHANGE 'U' USE"
+ retreat_block: "'R' RETREAT 'B' BLOCK"
enhdialogs:
character:
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 381ca3f9085..290b5af605f 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -32,9 +32,10 @@ void Combat::clear() {
Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
- _val1 = _val8 = _val9 = _val10 = 0;
+ _val1 = _val2 = _val3 = _val4 = _val5 = 0;
+ _val8 = _val9 = _val10 = 0;
_monsterP = nullptr;
- _monsterIndex = 0;
+ _monsterIndex = _currentChar = 0;
// TODO: clear everything
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index c7b4568411c..47e4e030a54 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -42,7 +42,8 @@ protected:
byte _arr3[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
int _val1, _val8, _val9, _val10;
- int _monsterIndex;
+ int _monsterIndex, _currentChar;
+ char _val2, _val3, _val4, _val5;
Combat() { clear(); }
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 8b227f7c5b3..1f4e35506d0 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -46,6 +46,9 @@ bool Combat::msgFocus(const FocusMessage &msg) {
loadArrays();
+ // TODO: Replace with correct selection of starting char
+ g_globals->_currCharacter = &g_globals->_party[0];
+
return true;
}
@@ -53,7 +56,7 @@ void Combat::draw() {
//Game::Encounter &enc = g_globals->_encounters;
clearSurface();
- writeString(10, 10, "TODO: COMBAT VIEW");
+ writeOptions();
}
void Combat::timeout() {
@@ -64,11 +67,74 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
return true;
}
+void Combat::writeOptions() {
+ resetBottom();
+ writeString(0, 20, STRING["dialogs.combat.options_for"]);
+ writeString(0, 22, g_globals->_currCharacter->_name);
+
+ switch (_currentChar) {
+ case 0:
+ writeChar(3, 3, (unsigned char)'\xB1');
+ break;
+ case 1:
+ writeChar(7, 3, (unsigned char)'\xB2');
+ break;
+ case 2:
+ writeChar(3, 4, (unsigned char)'\xB3');
+ break;
+ case 3:
+ writeChar(7, 4, (unsigned char)'\xB4');
+ break;
+ case 4:
+ writeChar(3, 5, (unsigned char)'\xB5');
+ break;
+ case 5:
+ writeChar(7, 5, (unsigned char)'\xB6');
+ break;
+ default:
+ break;
+ }
+
+ bool canAttack = _canAttack[_currentChar];
+ if (canAttack) {
+ writeAttackOptions();
+ _val5 = 'A';
+ _val2 = 'F';
+
+ // Archers can always attack
+ canAttack = g_globals->_currCharacter->_class == ARCHER;
+ }
+ if (canAttack && g_globals->_currCharacter->_v6a) {
+ _val3 = 'S';
+ writeShootOption();
+ }
+
+ if (g_globals->_currCharacter->_sp._current) {
+ writeCastOption();
+ _val4 = 'C';
+ }
+
+ writeString(16, 22, STRING["dialogs.combat.exchange_use"]);
+ writeString(16, 23, STRING["dialogs.combat.retreat_block"]);
+}
+
void Combat::writeAttackOptions() {
writeString(16, 20, STRING["dialogs.combat.attack"]);
writeString(16, 21, STRING["dialogs.combat.fight"]);
}
+void Combat::writeCastOption() {
+ writeString(30, 21, STRING["dialogs.combat.cast"]);
+}
+
+void Combat::writeShootOption() {
+ writeString(30, 20, STRING["dialogs.combat.shoot"]);
+}
+
+void Combat::resetBottom() {
+ clearLines(20, 24);
+ _val2 = _val3 = _val4 = _val5 = ' ';
+}
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 04fff81b192..70720f7e2f1 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -36,7 +36,11 @@ private:
};
Mode _mode = BATTLE;
+ void writeOptions();
void writeAttackOptions();
+ void writeCastOption();
+ void writeShootOption();
+ void resetBottom();
public:
Combat();
virtual ~Combat() {}
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index dbf11db5a8a..3dbce7b048a 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -36,7 +36,7 @@ TextView::TextView(const Common::String &name, UIElement *owner) :
UIElement(name, owner) {
}
-void TextView::writeChar(char c) {
+void TextView::writeChar(unsigned char c) {
if (c == '\r' || c == '\n') {
_textPos.x = 0;
_textPos.y++;
@@ -52,7 +52,7 @@ void TextView::writeChar(char c) {
}
}
-void TextView::writeChar(int x, int y, char c) {
+void TextView::writeChar(int x, int y, unsigned char c) {
_textPos.x = x;
_textPos.y = y;
writeChar(c);
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index a47db3f3c7c..df5e9f7dcbf 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -47,8 +47,8 @@ protected:
/**
* Write a character
*/
- void writeChar(char c);
- void writeChar(int x, int y, char c);
+ void writeChar(unsigned char c);
+ void writeChar(int x, int y, unsigned char c);
/**
* Write some text
diff --git a/engines/mm/utils/bitmap_font.cpp b/engines/mm/utils/bitmap_font.cpp
index 018a29c2a4e..8a2a90b70b9 100644
--- a/engines/mm/utils/bitmap_font.cpp
+++ b/engines/mm/utils/bitmap_font.cpp
@@ -58,13 +58,19 @@ bool BitmapFont::load(const Common::String &filename) {
}
void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ // Get the fg/bg color. When the character is >= 128,
+ // the colors are reversed from normal
+ byte fgColor = (chr < 128) ? color : 0;
+ byte bgColor = (chr < 128) ? 0 : color;
+ chr &= 0x7f;
+
const Graphics::ManagedSurface &c = _chars[chr - _startingChar];
for (int yCtr = 0; yCtr < c.h; ++yCtr) {
const byte *srcP = (const byte *)c.getBasePtr(0, yCtr);
for (int xCtr = 0; xCtr < c.w; ++xCtr, ++srcP) {
dst->hLine(x + xCtr, y + yCtr, x + xCtr,
- *srcP ? 0 : color);
+ *srcP ? bgColor : fgColor);
}
}
}
Commit: 8bedce9ae260c3f809b1fa4184e6297acd6682cb
https://github.com/scummvm/scummvm/commit/8bedce9ae260c3f809b1fa4184e6297acd6682cb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Added setupCanAttacks method
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/maps/map.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 290b5af605f..1cc21de62be 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -36,6 +36,7 @@ void Combat::clear() {
_val8 = _val9 = _val10 = 0;
_monsterP = nullptr;
_monsterIndex = _currentChar = 0;
+ _attackerVal = 0;
// TODO: clear everything
}
@@ -67,6 +68,85 @@ void Combat::monsterIndexOf() {
}
}
+void Combat::setupCanAttacks() {
+ const Encounter &enc = g_globals->_encounters;
+ const Maps::Map &map = *g_maps->_currentMap;
+ Common::fill(&_canAttack[0], &_canAttack[MAX_PARTY_SIZE], false);
+
+ if ((int8)map[Maps::MAP_ID] < 0) {
+ if (enc._encounterFlag != FORCE_SURPRISED) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (i < (MAX_PARTY_SIZE - 1)) {
+ _canAttack[i] = true;
+ } else {
+ _canAttack[MAX_PARTY_SIZE - 1] =
+ getRandomNumber(1, 100) <= 10;
+ }
+ }
+
+ setupCanAttacks();
+ return;
+ }
+ } else {
+ if (enc._encounterFlag != FORCE_SURPRISED) {
+ _canAttack[0] = true;
+ if (g_globals->_party.size() > 1)
+ _canAttack[1] = true;
+ if (g_globals->_party.size() > 2)
+ checkLeftWall();
+ if (g_globals->_party.size() > 3)
+ checkRightWall();
+ if (g_globals->_party.size() > 4) {
+ if (_canAttack[2] && getRandomNumber(1, 100) <= 5)
+ _canAttack[4] = true;
+ }
+ if (g_globals->_party.size() > 5) {
+ if (_canAttack[3] && getRandomNumber(1, 100) <= 5)
+ _canAttack[5] = true;
+ }
+
+ setupAttackerVal();
+ return;
+ }
+ }
+
+ // Entire party is allowed to attack
+ Common::fill(&_canAttack[0], &_canAttack[g_globals->_party.size()], true);
+ setupAttackerVal();
+}
+
+void Combat::setupAttackerVal() {
+ _attackerVal = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (_canAttack[i])
+ ++_attackerVal;
+ }
+
+ _attackerVal = getRandomNumber(1, _attackerVal + 1) - 1;
+}
+
+void Combat::checkLeftWall() {
+ Maps::Maps &maps = *g_maps;
+
+ if ((maps._currentWalls & maps._leftMask) &&
+ getRandomNumber(1, 100) >= 26) {
+ _canAttack[2] = false;
+ } else {
+ _canAttack[2] = true;
+ }
+}
+
+void Combat::checkRightWall() {
+ Maps::Maps &maps = *g_maps;
+
+ if ((maps._currentWalls & maps._rightMask) &&
+ getRandomNumber(1, 100) >= 26) {
+ _canAttack[3] = false;
+ } else {
+ _canAttack[3] = true;
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 47e4e030a54..3f66949a342 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -44,6 +44,7 @@ protected:
int _val1, _val8, _val9, _val10;
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
+ int _attackerVal;
Combat() { clear(); }
@@ -53,7 +54,35 @@ protected:
void clear();
void loadArrays();
+
+ /**
+ * Sets the _monsterIndex to the index of
+ * _monsterP in the monster list
+ */
void monsterIndexOf();
+
+ /**
+ * Sets up the flags for whether each character
+ * in the party can attack from their position.
+ */
+ void setupCanAttacks();
+
+ /**
+ * Chooses the starting character to
+ */
+ void setupAttackerVal();
+
+ /**
+ * Checks whether the third party member
+ * is blocked by a left wall
+ */
+ void checkLeftWall();
+
+ /**
+ * Checks whether the fourth party member
+ * is blocked by a right wall
+ */
+ void checkRightWall();
};
} // namespace Game
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 0a913a54a29..f7c00438744 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -37,6 +37,7 @@ namespace Maps {
class Maps;
enum DataOffset {
+ MAP_ID = 0,
MAP_FLEE_THRESHOLD = 22,
MAP_FLEE_X = 23,
MAP_FLEE_Y = 24,
Commit: 2e637f238a742b36840c97f68cb5e28c9123bf2e
https://github.com/scummvm/scummvm/commit/2e637f238a742b36840c97f68cb5e28c9123bf2e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Added writeHandicap method
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 30fc9a42311..3723e22daaa 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -293,6 +293,9 @@
shoot: "'S' SHOOT"
exchange_use: "'E' EXCHANGE 'U' USE"
retreat_block: "'R' RETREAT 'B' BLOCK"
+ even: "EVEN"
+ party_plus: "PARTY +"
+ monster_plus: "MONSTER +"
enhdialogs:
character:
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 1cc21de62be..1262473081a 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -33,7 +33,8 @@ void Combat::clear() {
Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
- _val8 = _val9 = _val10 = 0;
+ _handicap = HANDICAP_EVEN;
+ _val9 = _val10 = 0;
_monsterP = nullptr;
_monsterIndex = _currentChar = 0;
_attackerVal = 0;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3f66949a342..7293ba65e1c 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -41,10 +41,15 @@ protected:
byte _arr2[MAX_COMBAT_MONSTERS];
byte _arr3[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
- int _val1, _val8, _val9, _val10;
+ int _val1, _val9, _val10;
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
int _attackerVal;
+ enum Handicap {
+ HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
+ HANDICAP_MONSTER = 2
+ };
+ Handicap _handicap = HANDICAP_EVEN;
Combat() { clear(); }
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 1f4e35506d0..9623b9abccc 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -45,6 +45,7 @@ bool Combat::msgFocus(const FocusMessage &msg) {
_party.push_back(&g_globals->_party[i]);
loadArrays();
+ setupCanAttacks();
// TODO: Replace with correct selection of starting char
g_globals->_currCharacter = &g_globals->_party[0];
@@ -56,6 +57,8 @@ void Combat::draw() {
//Game::Encounter &enc = g_globals->_encounters;
clearSurface();
+ writeHandicap();
+
writeOptions();
}
@@ -136,6 +139,23 @@ void Combat::resetBottom() {
_val2 = _val3 = _val4 = _val5 = ' ';
}
+void Combat::writeHandicap() {
+ writeString(0, 13, " ");
+ _textPos.x = 0;
+
+ switch (_handicap) {
+ case HANDICAP_EVEN:
+ writeString(STRING["dialogs.combat.even"]);
+ break;
+ case HANDICAP_PARTY:
+ writeString(STRING["dialogs.combat.party_plus"]);
+ break;
+ case HANDICAP_MONSTER:
+ writeString(STRING["dialogs.combat.monster_plus"]);
+ break;
+ }
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 70720f7e2f1..efe6ba11a77 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -41,6 +41,8 @@ private:
void writeCastOption();
void writeShootOption();
void resetBottom();
+ void writeHandicap();
+
public:
Combat();
virtual ~Combat() {}
Commit: ced1c79cc50bca8619a8ccdb6841415223fae413
https://github.com/scummvm/scummvm/commit/ced1c79cc50bca8619a8ccdb6841415223fae413
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Added setupHandicap method
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 1262473081a..084e5338b70 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -33,15 +33,16 @@ void Combat::clear() {
Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
+ _val10 = 0;
+ _handicap1 = _handicap2 = 0;
+ _handicap3 = _handicap4 = 0;
_handicap = HANDICAP_EVEN;
- _val9 = _val10 = 0;
_monsterP = nullptr;
_monsterIndex = _currentChar = 0;
_attackerVal = 0;
// TODO: clear everything
}
-
void Combat::loadArrays() {
Game::Encounter &enc = g_globals->_encounters;
@@ -148,6 +149,34 @@ void Combat::checkRightWall() {
}
}
+void Combat::setupHandicap() {
+ _handicap2 = _handicap3 = 40;
+ _handicap1 = getRandomNumber(1, 7);
+
+ int val = getRandomNumber(1, 7);
+ if (val < _handicap1) {
+ SWAP(val, _handicap1);
+ _handicap4 = val - _handicap1;
+
+ if (_handicap4) {
+ _handicap = HANDICAP_MONSTER;
+ _handicap2 += _handicap4;
+ return;
+ }
+ } else if (val > _handicap1) {
+ _handicap4 -= _handicap1;
+
+ if (_handicap4) {
+ _handicap = HANDICAP_PARTY;
+ _handicap3 += _handicap4;
+ return;
+ }
+ }
+
+ _handicap = HANDICAP_EVEN;
+ _handicap4 = 0;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 7293ba65e1c..3eb5f1568ed 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -41,9 +41,11 @@ protected:
byte _arr2[MAX_COMBAT_MONSTERS];
byte _arr3[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
- int _val1, _val9, _val10;
+ int _val1, _val10;
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
+ int _handicap1, _handicap2;
+ int _handicap3, _handicap4;
int _attackerVal;
enum Handicap {
HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
@@ -88,6 +90,11 @@ protected:
* is blocked by a right wall
*/
void checkRightWall();
+
+ /**
+ * Sets up the handicap for the encounter
+ */
+ void setupHandicap();
};
} // namespace Game
Commit: 11254c9e71d7068e46cbea2a328cc7604d9165a2
https://github.com/scummvm/scummvm/commit/11254c9e71d7068e46cbea2a328cc7604d9165a2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:10+01:00
Commit Message:
MM: MM1: Added the writeStaticContent method
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3723e22daaa..428234d64eb 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -286,6 +286,13 @@
alignment_slips: "*** ALIGNMENT SLIPS ***"
combat: "COMBAT!"
combat:
+ combat: "COMBAT"
+ round: "ROUND #:"
+ delay: "D DELAY"
+ protect: "P PROTECT"
+ quickref: "Q QUICKREF"
+ view_char: "# VIEW CH"
+ handicap: "HANDICAP"
options_for: "OPTIONS FOR: "
attack: "'A' ATTACK(A)"
cast: "'C' CAST"
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 9623b9abccc..b3f37f87f94 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -57,6 +57,7 @@ void Combat::draw() {
//Game::Encounter &enc = g_globals->_encounters;
clearSurface();
+ writeStaticContent();
writeHandicap();
writeOptions();
@@ -156,6 +157,20 @@ void Combat::writeHandicap() {
}
}
+void Combat::writeStaticContent() {
+ writeString(0, 0, STRING["dialogs.combat.combat"]);
+ writeString(0, 1, STRING["dialogs.combat.round"]);
+ writeString(0, 7, STRING["dialogs.combat.delay"]);
+ writeString(0, 8, STRING["dialogs.combat.protect"]);
+ writeString(0, 9, STRING["dialogs.combat.quickref"]);
+ writeString(0, 10, STRING["dialogs.combat.view_char"]);
+ writeString(0, 12, STRING["dialogs.combat.handicap"]);
+
+ _textPos = Common::Point(0, 15);
+ for (int i = 0; i < 40; ++i)
+ writeChar('-');
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index efe6ba11a77..ec8d3db7f81 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -41,8 +41,17 @@ private:
void writeCastOption();
void writeShootOption();
void resetBottom();
+
+ /**
+ * Write the encounter handicap
+ */
void writeHandicap();
+ /**
+ * Write out all the static content
+ */
+ void writeStaticContent();
+
public:
Combat();
virtual ~Combat() {}
Commit: a4992c9eb1cc15ba3bff567b004debdc7f9c5b22
https://github.com/scummvm/scummvm/commit/a4992c9eb1cc15ba3bff567b004debdc7f9c5b22
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Added writeRound, fixed writeHandicap
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 084e5338b70..60040a0998a 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -33,7 +33,6 @@ void Combat::clear() {
Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
- _val10 = 0;
_handicap1 = _handicap2 = 0;
_handicap3 = _handicap4 = 0;
_handicap = HANDICAP_EVEN;
@@ -41,6 +40,8 @@ void Combat::clear() {
_monsterIndex = _currentChar = 0;
_attackerVal = 0;
// TODO: clear everything
+
+ _roundNum = 1;
}
void Combat::loadArrays() {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3eb5f1568ed..2998ebe053b 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -41,7 +41,8 @@ protected:
byte _arr2[MAX_COMBAT_MONSTERS];
byte _arr3[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
- int _val1, _val10;
+ int _val1;
+ int _roundNum;
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
int _handicap1, _handicap2;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index b3f37f87f94..ac89311d9d5 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -46,6 +46,7 @@ bool Combat::msgFocus(const FocusMessage &msg) {
loadArrays();
setupCanAttacks();
+ setupHandicap();
// TODO: Replace with correct selection of starting char
g_globals->_currCharacter = &g_globals->_party[0];
@@ -59,6 +60,7 @@ void Combat::draw() {
clearSurface();
writeStaticContent();
writeHandicap();
+ writeRound();
writeOptions();
}
@@ -140,6 +142,20 @@ void Combat::resetBottom() {
_val2 = _val3 = _val4 = _val5 = ' ';
}
+void Combat::writeStaticContent() {
+ writeString(0, 0, STRING["dialogs.combat.combat"]);
+ writeString(0, 1, STRING["dialogs.combat.round"]);
+ writeString(0, 7, STRING["dialogs.combat.delay"]);
+ writeString(0, 8, STRING["dialogs.combat.protect"]);
+ writeString(0, 9, STRING["dialogs.combat.quickref"]);
+ writeString(0, 10, STRING["dialogs.combat.view_char"]);
+ writeString(0, 12, STRING["dialogs.combat.handicap"]);
+
+ _textPos = Common::Point(0, 15);
+ for (int i = 0; i < 40; ++i)
+ writeChar('-');
+}
+
void Combat::writeHandicap() {
writeString(0, 13, " ");
_textPos.x = 0;
@@ -150,25 +166,17 @@ void Combat::writeHandicap() {
break;
case HANDICAP_PARTY:
writeString(STRING["dialogs.combat.party_plus"]);
+ writeNumber(_handicap4);
break;
case HANDICAP_MONSTER:
writeString(STRING["dialogs.combat.monster_plus"]);
+ writeNumber(_handicap4);
break;
}
}
-void Combat::writeStaticContent() {
- writeString(0, 0, STRING["dialogs.combat.combat"]);
- writeString(0, 1, STRING["dialogs.combat.round"]);
- writeString(0, 7, STRING["dialogs.combat.delay"]);
- writeString(0, 8, STRING["dialogs.combat.protect"]);
- writeString(0, 9, STRING["dialogs.combat.quickref"]);
- writeString(0, 10, STRING["dialogs.combat.view_char"]);
- writeString(0, 12, STRING["dialogs.combat.handicap"]);
-
- _textPos = Common::Point(0, 15);
- for (int i = 0; i < 40; ++i)
- writeChar('-');
+void Combat::writeRound() {
+ writeNumber(7, 1, _roundNum);
}
} // namespace Views
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index ec8d3db7f81..15751c50c81 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -52,6 +52,11 @@ private:
*/
void writeStaticContent();
+ /**
+ * Write out the round number
+ */
+ void writeRound();
+
public:
Combat();
virtual ~Combat() {}
Commit: d882f2f01995828447707ae4964ab4cf82077333
https://github.com/scummvm/scummvm/commit/d882f2f01995828447707ae4964ab4cf82077333
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Added writePartyNumbers method
Changed paths:
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index ac89311d9d5..d957afec45d 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -61,6 +61,7 @@ void Combat::draw() {
writeStaticContent();
writeHandicap();
writeRound();
+ writePartyNumbers();
writeOptions();
}
@@ -179,6 +180,14 @@ void Combat::writeRound() {
writeNumber(7, 1, _roundNum);
}
+void Combat::writePartyNumbers() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ writeChar(2 + 4 * (i % 2), 3 + (i / 2),
+ _canAttack[i] ? '+' : ' ');
+ writeChar('1' + i);
+ }
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 15751c50c81..6a4ea65729d 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -57,6 +57,12 @@ private:
*/
void writeRound();
+ /**
+ * Writes out the party member numbers,
+ * with a plus next to each if they can attack
+ */
+ void writePartyNumbers();
+
public:
Combat();
virtual ~Combat() {}
Commit: 021528222f3365084cae360de863803660b7386b
https://github.com/scummvm/scummvm/commit/021528222f3365084cae360de863803660b7386b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Simplify the checkLeft/RightWall methods
Changed paths:
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 60040a0998a..e13c8ca6244 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -131,23 +131,15 @@ void Combat::setupAttackerVal() {
void Combat::checkLeftWall() {
Maps::Maps &maps = *g_maps;
- if ((maps._currentWalls & maps._leftMask) &&
- getRandomNumber(1, 100) >= 26) {
- _canAttack[2] = false;
- } else {
- _canAttack[2] = true;
- }
+ _canAttack[2] = !(maps._currentWalls & maps._leftMask) ||
+ getRandomNumber(1, 100) <= 25;
}
void Combat::checkRightWall() {
Maps::Maps &maps = *g_maps;
- if ((maps._currentWalls & maps._rightMask) &&
- getRandomNumber(1, 100) >= 26) {
- _canAttack[3] = false;
- } else {
- _canAttack[3] = true;
- }
+ _canAttack[3] = !(maps._currentWalls & maps._rightMask) ||
+ getRandomNumber(1, 100) <= 25;
}
void Combat::setupHandicap() {
Commit: 15dfb0849f3ed3c74035349e79e30d33820fb995
https://github.com/scummvm/scummvm/commit/15dfb0849f3ed3c74035349e79e30d33820fb995
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Clean up encounter type, added optional parameter to console command
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index a4ce29024c4..76b120170b1 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -268,6 +268,13 @@ bool Console::cmdCast(int argc, const char **argv) {
}
bool Console::cmdEncounter(int argc, const char **argv) {
+ if (argc > 1) {
+ int encType = strToInt(argv[1]);
+ if (encType == -1 || encType == 0 || encType == 1)
+ g_globals->_encounters._encounterType =
+ (Game::EncounterType)encType;
+ }
+
g_globals->_encounters.execute();
return false;
}
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index e13c8ca6244..ca8c17a41fc 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -77,7 +77,7 @@ void Combat::setupCanAttacks() {
Common::fill(&_canAttack[0], &_canAttack[MAX_PARTY_SIZE], false);
if ((int8)map[Maps::MAP_ID] < 0) {
- if (enc._encounterFlag != FORCE_SURPRISED) {
+ if (enc._encounterType != FORCE_SURPRISED) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
if (i < (MAX_PARTY_SIZE - 1)) {
_canAttack[i] = true;
@@ -91,7 +91,7 @@ void Combat::setupCanAttacks() {
return;
}
} else {
- if (enc._encounterFlag != FORCE_SURPRISED) {
+ if (enc._encounterType != FORCE_SURPRISED) {
_canAttack[0] = true;
if (g_globals->_party.size() > 1)
_canAttack[1] = true;
@@ -113,7 +113,9 @@ void Combat::setupCanAttacks() {
}
}
- // Entire party is allowed to attack
+ // Entire party is allowed to attack, I guess
+ // because the monsters are surrounding the party,
+ // placing them within reach
Common::fill(&_canAttack[0], &_canAttack[g_globals->_party.size()], true);
setupAttackerVal();
}
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index a6eb9f1d28e..98d3886cbc5 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -55,7 +55,7 @@ public:
int _alignmentsChanged = 0;
int _monsterImgNum = 0;
int _monsterIndex = 0;
- EncounterType _encounterFlag = NORMAL_SURPRISED;
+ EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
public:
/**
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index da776f68f0c..7d2df75df8e 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -58,12 +58,12 @@ darkness:
}
// Encounter checks
- g_globals->_encounters._encounterFlag = NORMAL_SURPRISED;
+ g_globals->_encounters._encounterType = NORMAL_SURPRISED;
if (maps._currentState & 0x80) {
map.special();
} else if (_stepRandom) {
- g_globals->_encounters._encounterFlag = NORMAL_ENCOUNTER;
+ g_globals->_encounters._encounterType = NORMAL_ENCOUNTER;
_stepRandom = false;
g_globals->_encounters.execute();
} else {
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 8355f3cff0e..2f904e3f0ed 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -40,6 +40,10 @@ bool Encounter::msgFocus(const FocusMessage &msg) {
void Encounter::draw() {
Game::Encounter &enc = g_globals->_encounters;
+ // Clear the commands area
+ Graphics::ManagedSurface s = getSurface();
+ s.fillRect(Common::Rect(31 * 8, 0, 320, 17 * 8), 0);
+
switch (_mode) {
case ALERT:
writeString(9, 6, " ");
@@ -51,7 +55,7 @@ void Encounter::draw() {
case SURPRISED_BY_MONSTERS:
writeString(6, 21, STRING["dialogs.encounter.surprised"]);
- enc._encounterFlag = Game::FORCE_SURPRISED;
+ enc._encounterType = Game::FORCE_SURPRISED;
delaySeconds(2);
break;
@@ -61,10 +65,6 @@ void Encounter::draw() {
break;
case ENCOUNTER_OPTIONS: {
- // Clear the commands area
- Graphics::ManagedSurface s = getSurface();
- s.fillRect(Common::Rect(31 * 8, 0, 320, 17 * 8), 0);
-
// Write the encounter options
clearLines(20, 24);
writeString(0, 21, STRING["dialogs.encounter.options1"]);
@@ -157,9 +157,9 @@ void Encounter::timeout() {
switch (_mode) {
case ALERT:
// Finished displaying initial encounter alert
- if (enc._encounterFlag < 0 /* FORCE_SURPRISED */) {
+ if (enc._encounterType < 0 /* FORCE_SURPRISED */) {
_mode = SURPRISED_BY_MONSTERS;
- } else if (enc._encounterFlag == Game::NORMAL_SURPRISED ||
+ } else if (enc._encounterType == Game::NORMAL_SURPRISED ||
/* ENCOUNTER_OPTIONS */
g_engine->getRandomNumber(1, 100) > map[21]) {
// Potentially surprised. Check for guard dog spell
Commit: fa0b614e9cec24004a89541a97f948795426031b
https://github.com/scummvm/scummvm/commit/fa0b614e9cec24004a89541a97f948795426031b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Change map offsets to use DataOffset enum constants
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.h
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/locations/market.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/spells/location.cpp
engines/mm/mm1/views/spells/teleport.cpp
engines/mm/mm1/views_enh/locations/market.cpp
engines/mm/mm1/views_enh/locations/temple.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 428234d64eb..385322282bc 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -303,6 +303,18 @@
even: "EVEN"
party_plus: "PARTY +"
monster_plus: "MONSTER +"
+ and_goes_down: "AND GOES DOWN!!!"
+ dies: "DIES!"
+ status:
+ 0: "(PARALYZE)"
+ 1: "(WEBBED) "
+ 2: "(HELD) "
+ 3: "(ASLEEP) "
+ 4: "(MINDLESS)"
+ 5: "(SILENCED)"
+ 6: "(BLINDED) "
+ 7: "(AFRAID) "
+ 8: "(DEAD) "
enhdialogs:
character:
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index aca4e04105a..cabf42f9453 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -31,6 +31,12 @@ namespace MM1 {
#define MONSTERS_COUNT 195
+enum MonsterStatus {
+ MON_PARALYZED = 0, MON_WEBBED = 1, MON_HELD = 2,
+ MON_ASLEEP = 3, MON_MINDLESS = 4, MON_SILENCED = 5,
+ MON_BLINDED = 6, MON_AFRAID = 7, MON_DEAD = 8
+};
+
struct Monster {
Common::String _name; // char _name[15];
byte _count;
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index cceb497d9dd..7782492d07e 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -295,18 +295,21 @@ SpellResult Spells::cleric45_restoreAlignment(Character *chr) {
SpellResult Spells::cleric48_surface(Character *chr) {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
- if (map[46] & 4) {
+ if (map[Maps::MAP_FLAGS] & 4) {
return SR_FAILED;
} else {
- maps._mapPos = Common::Point(map[42], map[43]);
- maps.changeMap(map[11] & (map[12] << 8), map[13]);
+ maps._mapPos = Common::Point(map[Maps::MAP_SURFACE_X],
+ map[Maps::MAP_SURFACE_Y]);
+ maps.changeMap(map[Maps::MAP_SURFACE_DEST_ID1] &
+ (map[Maps::MAP_SURFACE_DEST_ID2] << 8),
+ map[Maps::MAP_SURFACE_DEST_SECTION]);
return SR_SUCCESS_SILENT;
}
}
SpellResult Spells::cleric52_dispelMagic(Character *chr) {
Maps::Map &map = *g_maps->_currentMap;
- if (g_engine->getRandomNumber(100) >= map[38]) {
+ if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DISPEL_THRESHOLD]) {
Common::fill(&g_globals->_spells._arr[0],
&g_globals->_spells._arr[18], 0);
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 40cbba9c1e4..74ea15c3af0 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -63,14 +63,14 @@ void Encounter::execute() {
maxRand = _levelOffset + _highestLevel;
if (maxRand >= 2) {
- int highestRand = map[33];
+ int highestRand = map[Maps::MAP_33];
maxRand = MIN(maxRand, highestRand);
comp = getRandomNumber(1, maxRand);
} else {
comp = 1;
}
- maxVal = map[47];
+ maxVal = map[Maps::MAP_47];
if (comp < maxVal) {
comp = MIN(maxVal, 10);
}
@@ -85,7 +85,7 @@ void Encounter::execute() {
_monsterIndex = (_monsterIndex + 1) & 0xff;
if (_monsterIndex < MAX_COMBAT_MONSTERS) {
- if (_monsterIndex >= map[34])
+ if (_monsterIndex >= map[Maps::MAP_MAX_MONSTERS])
goto exit_loop;
monsterP = getMonster();
@@ -100,7 +100,7 @@ void Encounter::execute() {
if (++_monsterIndex >= MAX_COMBAT_MONSTERS)
goto exit_loop;
- if (_monsterIndex >= map[34])
+ if (_monsterIndex >= map[Maps::MAP_MAX_MONSTERS])
goto exit_loop;
}
} else {
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 4744830eafa..77dd6a53396 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -117,7 +117,8 @@ void SpellCasting::setSpell(int spellIndex, int requiredSp, int requiredGems) {
if (SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
_spellState = SS_COMBAT_ONLY;
- else if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) && !(map[0] & 0x80))
+ else if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) &&
+ !(map[Maps::MAP_ID] & 0x80))
_spellState = SS_OUTDOORS_ONLY;
}
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 7d2df75df8e..8b3a6e6dd2a 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -51,7 +51,7 @@ void ViewBase::update() {
}
}
- if ((map[46] & 1) && !g_globals->_spells._s.light) {
+ if ((map[Maps::MAP_FLAGS] & 1) && !g_globals->_spells._s.light) {
darkness:
// TODO
_isDark = true;
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index f7c00438744..919d712f2c4 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -38,13 +38,28 @@ class Maps;
enum DataOffset {
MAP_ID = 0,
+ MAP_SURFACE_DEST_ID1 = 11,
+ MAP_SURFACE_DEST_ID2 = 12,
+ MAP_SURFACE_DEST_SECTION = 13,
+ MAP_20 = 20,
+ MAP_21 = 21,
MAP_FLEE_THRESHOLD = 22,
MAP_FLEE_X = 23,
MAP_FLEE_Y = 24,
MAP_SURRENDER_THRESHOLD = 25,
MAP_SURRENDER_X = 26,
MAP_SURRENDER_Y = 27,
- MAP_BRIBE_THRESHOLD = 28
+ MAP_BRIBE_THRESHOLD = 28,
+ MAP_33 = 33,
+ MAP_MAX_MONSTERS = 34,
+ MAP_35 = 35,
+ MAP_36 = 36,
+ MAP_37 = 37,
+ MAP_DISPEL_THRESHOLD = 38,
+ MAP_SURFACE_X = 42,
+ MAP_SURFACE_Y = 43,
+ MAP_FLAGS = 46,
+ MAP_47 = 47
};
enum WallType {
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index abfeedf40a3..e1b33a90bb4 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -293,8 +293,8 @@ void Map00::special21() {
void Map00::special22() {
Map &map = *g_maps->_currentMap;
- map[0x2f] = 3;
- map[0x21] = 6;
+ map[MM1::Maps::MAP_47] = 3;
+ map[MM1::Maps::MAP_33] = 6;
g_maps->clearSpecial();
}
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 2f904e3f0ed..84ce5d6a04c 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -161,10 +161,10 @@ void Encounter::timeout() {
_mode = SURPRISED_BY_MONSTERS;
} else if (enc._encounterType == Game::NORMAL_SURPRISED ||
/* ENCOUNTER_OPTIONS */
- g_engine->getRandomNumber(1, 100) > map[21]) {
+ g_engine->getRandomNumber(1, 100) > map[Maps::MAP_21]) {
// Potentially surprised. Check for guard dog spell
if (g_globals->_spells._s.guard_dog ||
- g_engine->getRandomNumber(1, 100) > map[20])
+ g_engine->getRandomNumber(1, 100) > map[Maps::MAP_20])
_mode = ENCOUNTER_OPTIONS;
else
_mode = SURPRISED_BY_MONSTERS;
diff --git a/engines/mm/mm1/views/locations/market.cpp b/engines/mm/mm1/views/locations/market.cpp
index f552e47d79f..dda2f6d7f81 100644
--- a/engines/mm/mm1/views/locations/market.cpp
+++ b/engines/mm/mm1/views/locations/market.cpp
@@ -38,7 +38,7 @@ bool Market::msgFocus(const FocusMessage &msg) {
send("View", ValueMessage(LOC_MARKET));
Maps::Map &map = *g_maps->_currentMap;
- _foodCost = FOOD_COST[map[0] - 1];
+ _foodCost = FOOD_COST[map[Maps::MAP_ID] - 1];
return true;
}
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 118b7ab5955..5fb334eb7a1 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -86,7 +86,7 @@ void Temple::changeCharacter(uint index) {
_isEradicated = false;
- int townNum = map[0];
+ int townNum = map[Maps::MAP_ID];
if (townNum < 1 || townNum >= 6)
townNum = 1;
--townNum;
@@ -198,7 +198,7 @@ void Temple::donate() {
Maps::Map &map = *g_maps->_currentMap;
Character &c = *g_globals->_currCharacter;
- int townNum = map[0];
+ int townNum = map[Maps::MAP_ID];
if (townNum < 1 || townNum >= 6)
townNum = 1;
--townNum;
diff --git a/engines/mm/mm1/views/spells/location.cpp b/engines/mm/mm1/views/spells/location.cpp
index 61e41db61fc..b34cd0c404b 100644
--- a/engines/mm/mm1/views/spells/location.cpp
+++ b/engines/mm/mm1/views/spells/location.cpp
@@ -64,16 +64,16 @@ void Location::draw() {
}
writeString(21, 0, STRING["dialogs.spells.location_sector"]);
- writeChar(map[35] & 0x7f);
+ writeChar(map[Maps::MAP_35] & 0x7f);
writeChar('-');
- writeChar(map[36] & 0x7f);
+ writeChar(map[Maps::MAP_36] & 0x7f);
writeString(21, 1, STRING["dialogs.spells.location_surface_x"]);
- if (map[37]) {
- writeNumber(map[42]);
+ if (map[Maps::MAP_37]) {
+ writeNumber(map[Maps::MAP_SURFACE_X]);
writeString(35, 1, "Y=");
- writeNumber(map[43]);
+ writeNumber(map[Maps::MAP_SURFACE_Y]);
writeString(22, 2, STRING["dialogs.spells.location_inside_x"]);
}
diff --git a/engines/mm/mm1/views/spells/teleport.cpp b/engines/mm/mm1/views/spells/teleport.cpp
index 10f47398e01..000071f4f8c 100644
--- a/engines/mm/mm1/views/spells/teleport.cpp
+++ b/engines/mm/mm1/views/spells/teleport.cpp
@@ -92,7 +92,7 @@ void Teleport::teleport() {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
- if (map[46] & 2) {
+ if (map[Maps::MAP_FLAGS] & 2) {
spellFailed();
} else {
diff --git a/engines/mm/mm1/views_enh/locations/market.cpp b/engines/mm/mm1/views_enh/locations/market.cpp
index 54bcc6a4562..04178149743 100644
--- a/engines/mm/mm1/views_enh/locations/market.cpp
+++ b/engines/mm/mm1/views_enh/locations/market.cpp
@@ -41,7 +41,7 @@ Market::Market() : Location("Market") {
bool Market::msgFocus(const FocusMessage &msg) {
Maps::Map &map = *g_maps->_currentMap;
- _foodCost = FOOD_COST[map[0] - 1];
+ _foodCost = FOOD_COST[map[Maps::MAP_ID] - 1];
return true;
}
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
index 52b03417707..22e6d45d666 100644
--- a/engines/mm/mm1/views_enh/locations/temple.cpp
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -121,7 +121,7 @@ void Temple::changeCharacter(uint index) {
_isEradicated = false;
- int townNum = map[0];
+ int townNum = map[Maps::MAP_ID];
if (townNum < 1 || townNum >= 6)
townNum = 1;
--townNum;
@@ -202,7 +202,7 @@ void Temple::donate() {
Maps::Map &map = *g_maps->_currentMap;
Character &c = *g_globals->_currCharacter;
- int townNum = map[0];
+ int townNum = map[Maps::MAP_ID];
if (townNum < 1 || townNum >= 6)
townNum = 1;
--townNum;
Commit: 61e5f45fa242d609fb1157ed20c5059ede33cb2f
https://github.com/scummvm/scummvm/commit/61e5f45fa242d609fb1157ed20c5059ede33cb2f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Use map data constants for dataByte/dataWord
Changed paths:
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
engines/mm/mm1/views/locations/tavern.cpp
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 8b3a6e6dd2a..2b78bd76070 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -165,7 +165,7 @@ void ViewBase::forward(KeybindingAction action) {
else
offset = 0;
- if (map.dataByte(30 + offset) == 4 &&
+ if (map.dataByte(Maps::MAP_30 + offset) == 4 &&
!g_globals->_spells._s.walk_on_water) {
Sound::sound(SOUND_1);
_dialogMessage = STRING["movement.obstructed.cant_swim"];
@@ -183,7 +183,7 @@ void ViewBase::forward(KeybindingAction action) {
Common::fill(&_arr2[0], &_arr2[8], 0);
- int maxVal = map.dataByte(29);
+ int maxVal = map[Maps::MAP_29];
if (g_engine->getRandomNumber(maxVal) == maxVal)
_stepRandom = true;
@@ -211,7 +211,7 @@ void ViewBase::backwards() {
Common::fill(&_arr2[0], &_arr2[8], 0);
- int maxVal = map.dataByte(29);
+ int maxVal = map[Maps::MAP_29];
if (g_engine->getRandomNumber(maxVal) == maxVal)
_stepRandom = true;
@@ -249,11 +249,11 @@ void ViewBase::bash() {
// No forward obstruction, so simply move forward
forward(KEYBIND_FORWARDS);
} else {
- int index = 32;
+ int index = Maps::MAP_32;
if (!(maps._currentWalls & maps._forwardMask & 0x55))
- index = 31;
+ index = Maps::MAP_31;
else if (!(maps._currentWalls & maps._forwardMask & 0x55))
- index = 30;
+ index = Maps::MAP_30;
if (map.dataByte(index) != 1) {
forward(KEYBIND_FORWARDS);
@@ -266,7 +266,7 @@ void ViewBase::bash() {
might = MIN(might, 255U);
// Check for busting
- uint threshold = map.dataByte(45);
+ uint threshold = map[Maps::MAP_45];
if (threshold && might >= threshold) {
map._states[maps._mapOffset + maps._forwardMask] ^=
(maps._forwardMask & 0x55);
@@ -274,7 +274,7 @@ void ViewBase::bash() {
}
// Check for trap being triggered
- if (g_engine->getRandomNumber(100) >= map.dataByte(48)) {
+ if (g_engine->getRandomNumber(100) >= map[Maps::MAP_48]) {
warning("TODO: trigger trap");
} else {
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 919d712f2c4..77b894ed952 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -38,9 +38,20 @@ class Maps;
enum DataOffset {
MAP_ID = 0,
+ MAP_1 = 1,
+ MAP_2 = 2,
+ MAP_4 = 4,
+ MAP_6 = 6,
+ MAP_8 = 8,
+ MAP_10 = 10,
MAP_SURFACE_DEST_ID1 = 11,
MAP_SURFACE_DEST_ID2 = 12,
MAP_SURFACE_DEST_SECTION = 13,
+ MAP_14 = 14,
+ MAP_16 = 16,
+ MAP_17 = 17,
+ MAP_18 = 18,
+ MAP_19 = 19,
MAP_20 = 20,
MAP_21 = 21,
MAP_FLEE_THRESHOLD = 22,
@@ -50,6 +61,10 @@ enum DataOffset {
MAP_SURRENDER_X = 26,
MAP_SURRENDER_Y = 27,
MAP_BRIBE_THRESHOLD = 28,
+ MAP_29 = 29,
+ MAP_30 = 30,
+ MAP_31 = 31,
+ MAP_32 = 32,
MAP_33 = 33,
MAP_MAX_MONSTERS = 34,
MAP_35 = 35,
@@ -58,8 +73,11 @@ enum DataOffset {
MAP_DISPEL_THRESHOLD = 38,
MAP_SURFACE_X = 42,
MAP_SURFACE_Y = 43,
+ MAP_44 = 44,
+ MAP_45 = 45,
MAP_FLAGS = 46,
- MAP_47 = 47
+ MAP_47 = 47,
+ MAP_48 = 48
};
enum WallType {
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index f9725dc57b3..6883ba14930 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -314,18 +314,18 @@ uint Maps::getIndex(uint16 id, byte section) {
}
void Maps::loadTiles() {
- _loadArea = _currentMap->dataByte(1);
- _loadId = _currentMap->dataWord(2);
+ _loadArea = _currentMap->dataByte(MAP_1);
+ _loadId = _currentMap->dataWord(MAP_2);
_loadSection = 1;
loadTile();
- _loadArea = _currentMap->dataByte(1);
- _loadId = _currentMap->dataWord(4);
+ _loadArea = _currentMap->dataByte(MAP_1);
+ _loadId = _currentMap->dataWord(MAP_4);
_loadSection = 2;
loadTile();
- _loadArea = _currentMap->dataByte(1);
- _loadId = _currentMap->dataWord(6);
+ _loadArea = _currentMap->dataByte(MAP_1);
+ _loadId = _currentMap->dataWord(MAP_6);
_loadSection = 3;
loadTile();
}
@@ -410,20 +410,20 @@ void Maps::step(const Common::Point &delta) {
int section = 0, id = 0;
if (_mapPos.x < 0) {
_mapPos.x = MAP_W - 1;
- id = _currentMap->dataWord(16);
- section = _currentMap->dataByte(14);
+ id = _currentMap->dataWord(MAP_16);
+ section = _currentMap->dataByte(MAP_14);
} else if (_mapPos.x >= MAP_W) {
_mapPos.x = 0;
- id = _currentMap->dataWord(11);
- section = _currentMap->dataByte(13);
+ id = _currentMap->dataWord(MAP_SURFACE_DEST_ID1);
+ section = _currentMap->dataByte(MAP_SURFACE_DEST_SECTION);
} else if (_mapPos.y < 0) {
_mapPos.y = MAP_H - 1;
- id = _currentMap->dataWord(17);
- section = _currentMap->dataByte(19);
+ id = _currentMap->dataWord(MAP_17);
+ section = _currentMap->dataByte(MAP_19);
} else if (_mapPos.y >= MAP_H) {
_mapPos.y = 0;
- id = _currentMap->dataWord(8);
- section = _currentMap->dataByte(10);
+ id = _currentMap->dataWord(MAP_8);
+ section = _currentMap->dataByte(MAP_10);
} else {
return;
}
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
index e810bc909c5..53ec01ca6ad 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
@@ -36,7 +36,7 @@ BlacksmithBuyArmor::BlacksmithBuyArmor() :
}
bool BlacksmithBuyArmor::msgFocus(const FocusMessage &msg) {
- int townNum = g_maps->_currentMap->dataByte(0);
+ int townNum = g_maps->_currentMap->dataByte(Maps::MAP_ID);
if (townNum < 1 || townNum >= 6)
townNum = 1;
_items = ARMOR[townNum - 1];
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
index 5136a6d7248..3f05165c22c 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
@@ -36,7 +36,7 @@ BlacksmithBuyMisc::BlacksmithBuyMisc() :
}
bool BlacksmithBuyMisc::msgFocus(const FocusMessage &msg) {
- int townNum = g_maps->_currentMap->dataByte(0);
+ int townNum = g_maps->_currentMap->dataByte(Maps::MAP_ID);
if (townNum < 1 || townNum >= 6)
townNum = 1;
_items = MISC[townNum - 1];
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
index 6c517e430d7..9baea69d525 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
@@ -36,7 +36,7 @@ BlacksmithBuyWeapons::BlacksmithBuyWeapons() :
}
bool BlacksmithBuyWeapons::msgFocus(const FocusMessage &msg) {
- int townNum = g_maps->_currentMap->dataByte(0);
+ int townNum = g_maps->_currentMap->dataByte(Maps::MAP_ID);
if (townNum < 1 || townNum >= 6)
townNum = 1;
_items = WEAPONS[townNum - 1];
diff --git a/engines/mm/mm1/views/locations/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
index 0fb08d0b352..53e87b06c9d 100644
--- a/engines/mm/mm1/views/locations/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -108,7 +108,7 @@ void Tavern::tipBartender() {
} else if (g_engine->getRandomNumber(3) != 3) {
displayMessage(STRING["dialogs.tavern.have_another_drink"]);
} else {
- int townNum = g_maps->_currentMap->dataByte(0);
+ int townNum = g_maps->_currentMap->dataByte(Maps::MAP_ID);
displayMessage(STRING[Common::String::format(
"dialogs.tavern.tips.%d_%d",
townNum, g_globals->_currCharacter->_numDrinks
Commit: f151a7c9bbb9ea8253a8be1f58ebb5e872b38fa9
https://github.com/scummvm/scummvm/commit/f151a7c9bbb9ea8253a8be1f58ebb5e872b38fa9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Added writing combat monster list
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 385322282bc..07a16ecc406 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -315,6 +315,7 @@
6: "(BLINDED) "
7: "(AFRAID) "
8: "(DEAD) "
+ wounded: "(WOUNDED) "
enhdialogs:
character:
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index ca8c17a41fc..660ca95c2b4 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -30,7 +30,7 @@ namespace Game {
void Combat::clear() {
Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_arr3[0], &_arr3[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_handicap1 = _handicap2 = 0;
@@ -71,6 +71,10 @@ void Combat::monsterIndexOf() {
}
}
+void Combat::monsterSetPtr(int monsterNum) {
+ _monsterP = &g_globals->_encounters._monsterList[monsterNum];
+}
+
void Combat::setupCanAttacks() {
const Encounter &enc = g_globals->_encounters;
const Maps::Map &map = *g_maps->_currentMap;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 2998ebe053b..a677f12a7a8 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -39,7 +39,7 @@ protected:
Monster *_monsterP;
byte _arr1[MAX_COMBAT_MONSTERS];
byte _arr2[MAX_COMBAT_MONSTERS];
- byte _arr3[MAX_COMBAT_MONSTERS];
+ byte _monsterStatus[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
int _val1;
int _roundNum;
@@ -69,6 +69,11 @@ protected:
*/
void monsterIndexOf();
+ /**
+ * Sets _monsterP to point to a specified monster
+ */
+ void monsterSetPtr(int monsterNum);
+
/**
* Sets up the flags for whether each character
* in the party can attack from their position.
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 74ea15c3af0..43409791734 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -81,7 +81,7 @@ void Encounter::execute() {
_levelIndex += comp;
_monsterNum = getRandomNumber(1, 16);
- _arr2[_monsterIndex] = _monsterNum;
+ _monsIndexes[_monsterIndex] = _monsterNum;
_monsterIndex = (_monsterIndex + 1) & 0xff;
if (_monsterIndex < MAX_COMBAT_MONSTERS) {
@@ -95,7 +95,7 @@ void Encounter::execute() {
assert(_monsterIndex > 0);
_arr1[_monsterIndex] = _arr1[_monsterIndex - 1];
_levelIndex += _arr1[_monsterIndex];
- _arr2[_monsterIndex] = _arr2[_monsterIndex - 1];
+ _monsIndexes[_monsterIndex] = _monsIndexes[_monsterIndex - 1];
if (++_monsterIndex >= MAX_COMBAT_MONSTERS)
goto exit_loop;
@@ -112,15 +112,15 @@ exit_loop:
_monsterList.clear();
for (int i = 0; i < _monsterIndex; ++i) {
- maxVal = (_arr1[i] - 1) * 16 + _arr2[i];
+ maxVal = (_arr1[i] - 1) * 16 + _monsIndexes[i];
if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
_arr1[i] = 10;
- _arr2[i] = getRandomNumber(1, MAX_COMBAT_MONSTERS);
+ _monsIndexes[i] = getRandomNumber(1, MAX_COMBAT_MONSTERS);
}
// Add monster details to list
_monsterNum16 = _arr1[i];
- const Monster &mons = g_globals->_monsters[_arr2[i]];
+ const Monster &mons = g_globals->_monsters[_monsIndexes[i]];
_monsterList.push_back(mons);
if (_monsterNum16 > _val9) {
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 98d3886cbc5..df8844c6126 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -45,7 +45,8 @@ private:
int _monsterNum16 = 0;
int _totalLevels = 0, _highestLevel = 0;
int _monsterNum = 0;
- byte _arr1[15], _arr2[15];
+ byte _arr1[MAX_COMBAT_MONSTERS];
+ byte _monsIndexes[MAX_COMBAT_MONSTERS];
void randomAdjust();
const Monster *getMonster();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index d957afec45d..7daf2dfe8a7 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -29,7 +29,8 @@ namespace MM {
namespace MM1 {
namespace Views {
-Combat::Combat() : TextView("Combat") {
+Combat::Combat() : TextView("Combat"),
+ _monsterList(g_globals->_encounters._monsterList) {
}
bool Combat::msgFocus(const FocusMessage &msg) {
@@ -62,6 +63,7 @@ void Combat::draw() {
writeHandicap();
writeRound();
writePartyNumbers();
+ writeMonsters();
writeOptions();
}
@@ -188,6 +190,61 @@ void Combat::writePartyNumbers() {
}
}
+void Combat::writeMonsters() {
+ const Game::Encounter &enc = g_globals->_encounters;
+
+ if (enc._monsterList.empty()) {
+ _textPos = Common::Point(10, 0);
+ writeSpaces(30);
+ } else {
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ _textPos = Common::Point(11, i);
+ writeChar(i < _attackerVal ? '+' : ' ');
+ writeChar('A' + i);
+ writeString(") ");
+ writeString(_monsterList[i]._name);
+ writeMonsterStatus(i);
+ }
+ }
+
+ for (; _textPos.y < 15; _textPos.y++) {
+ _textPos.x = 10;
+ writeSpaces(30);
+ }
+}
+
+void Combat::writeMonsterStatus(int monsterNum) {
+ monsterSetPtr(monsterNum);
+ byte statusBits = _monsterStatus[monsterNum];
+
+ if (statusBits) {
+ writeDots();
+
+ int status;
+ if (statusBits == 0xff) {
+ status = MON_DEAD;
+ } else {
+ for (status = MON_PARALYZED; !(statusBits & 0x80);
+ ++status, statusBits <<= 1) {
+ }
+ }
+
+ writeString(STRING[Common::String::format("dialogs.combat.status.%d",
+ status)]);
+ } else if (_arr1[monsterNum] != _monsterP->_field11) {
+ writeDots();
+ writeString(STRING["dialogs.combat.status.wounded"]);
+ } else {
+ writeSpaces(40 - _textPos.x);
+ }
+}
+
+void Combat::writeDots() {
+ while (_textPos.x < 30)
+ writeChar('.');
+}
+
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 6a4ea65729d..189c70ceefa 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -35,6 +35,7 @@ private:
BATTLE
};
Mode _mode = BATTLE;
+ Common::Array<Monster> &_monsterList;
void writeOptions();
void writeAttackOptions();
@@ -63,6 +64,21 @@ private:
*/
void writePartyNumbers();
+ /**
+ * Write the monsters list
+ */
+ void writeMonsters();
+
+ /**
+ * Write out a monster's status
+ */
+ void writeMonsterStatus(int monsterNum);
+
+ /**
+ * Write out a series of dots
+ */
+ void writeDots();
+
public:
Combat();
virtual ~Combat() {}
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 3dbce7b048a..f3e7fa42882 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -89,6 +89,11 @@ void TextView::newLine() {
_textPos.y++;
}
+void TextView::writeSpaces(size_t count) {
+ for (size_t i = 0; i < count; ++i)
+ writeChar(' ');
+}
+
void TextView::clearSurface() {
UIElement::clearSurface();
_textPos.x = _textPos.y = 0;
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index df5e9f7dcbf..cd6f4487abf 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -67,6 +67,11 @@ protected:
*/
void newLine();
+ /**
+ * Write out spaces
+ */
+ void writeSpaces(size_t count);
+
/**
* Clear the surface
*/
Commit: e4959067e3a496c1e14d459abaae2b3a28638dce
https://github.com/scummvm/scummvm/commit/e4959067e3a496c1e14d459abaae2b3a28638dce
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:11+01:00
Commit Message:
MM: MM1: Added writeParty method
Changed paths:
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 7daf2dfe8a7..332d644a983 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -34,13 +34,12 @@ Combat::Combat() : TextView("Combat"),
}
bool Combat::msgFocus(const FocusMessage &msg) {
- Game::Encounter &enc = g_globals->_encounters;
_mode = BATTLE;
// Clear combat data
clear();
- _monstersCount = enc._monsterList.size();
+ _monstersCount = _monsterList.size();
_party.clear();
for (uint i = 0; i < g_globals->_party.size(); ++i)
_party.push_back(&g_globals->_party[i]);
@@ -64,6 +63,7 @@ void Combat::draw() {
writeRound();
writePartyNumbers();
writeMonsters();
+ writeParty();
writeOptions();
}
@@ -191,13 +191,11 @@ void Combat::writePartyNumbers() {
}
void Combat::writeMonsters() {
- const Game::Encounter &enc = g_globals->_encounters;
-
- if (enc._monsterList.empty()) {
+ if (_monsterList.empty()) {
_textPos = Common::Point(10, 0);
writeSpaces(30);
} else {
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (int i = 0; i < (int)_monsterList.size(); ++i) {
_textPos = Common::Point(11, i);
writeChar(i < _attackerVal ? '+' : ' ');
writeChar('A' + i);
@@ -244,6 +242,19 @@ void Combat::writeDots() {
writeChar('.');
}
+void Combat::writeParty() {
+ clearPartyArea();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ writeChar(1 + 21 * (i % 2), 16 + (i / 2), '1' + i);
+ writeString(") ");
+ writeString(g_globals->_party[i]._name);
+ }
+}
+
+void Combat::clearPartyArea() {
+ clearLines(16, 18);
+}
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 189c70ceefa..0ff32152747 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -79,6 +79,16 @@ private:
*/
void writeDots();
+ /**
+ * Writes out the party members
+ */
+ void writeParty();
+
+ /**
+ * Clears the party area
+ */
+ void clearPartyArea();
+
public:
Combat();
virtual ~Combat() {}
Commit: 9d1017a2ce5e548caf78cffbec1f4a4a3d8615fe
https://github.com/scummvm/scummvm/commit/9d1017a2ce5e548caf78cffbec1f4a4a3d8615fe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:12+01:00
Commit Message:
MM: MM1: Starting to implement combat dialog main loop
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 660ca95c2b4..47b9d04adb9 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -32,6 +32,7 @@ void Combat::clear() {
Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
+ Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_handicap1 = _handicap2 = 0;
_handicap3 = _handicap4 = 0;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index a677f12a7a8..913f557bab8 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -41,6 +41,7 @@ protected:
byte _arr2[MAX_COMBAT_MONSTERS];
byte _monsterStatus[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
+ int _arr3[MAX_PARTY_SIZE / 2];
int _val1;
int _roundNum;
int _monsterIndex, _currentChar;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 332d644a983..767ef929a35 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -34,8 +34,6 @@ Combat::Combat() : TextView("Combat"),
}
bool Combat::msgFocus(const FocusMessage &msg) {
- _mode = BATTLE;
-
// Clear combat data
clear();
@@ -48,8 +46,7 @@ bool Combat::msgFocus(const FocusMessage &msg) {
setupCanAttacks();
setupHandicap();
- // TODO: Replace with correct selection of starting char
- g_globals->_currCharacter = &g_globals->_party[0];
+ combatLoop();
return true;
}
@@ -65,7 +62,13 @@ void Combat::draw() {
writeMonsters();
writeParty();
- writeOptions();
+ switch (_mode) {
+ case SELECT_OPTION:
+ writeOptions();
+ break;
+ default:
+ break;
+ }
}
void Combat::timeout() {
@@ -256,6 +259,45 @@ void Combat::clearPartyArea() {
clearLines(16, 18);
}
+void Combat::combatLoop() {
+ if (_monsterIndex != 0) {
+ selectParty();
+ } else {
+ selectMonster();
+ }
+}
+
+void Combat::selectMonster() {
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ // TODO
+ }
+
+ // TODO
+}
+
+void Combat::selectParty() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ int speed = c._speed._current;
+ if (speed && speed >= _handicap2) {
+ if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
+ // Character is enabled
+ _mode = SELECT_OPTION;
+ return;
+ }
+ }
+ }
+
+ loop1();
+}
+
+void Combat::loop1() {
+ // TODO
+}
+
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 0ff32152747..bc679e83b26 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -32,9 +32,9 @@ namespace Views {
class Combat : public TextView, public Game::Combat {
private:
enum Mode {
- BATTLE
+ SELECT_OPTION, FIGHT_WHICH
};
- Mode _mode = BATTLE;
+ Mode _mode = SELECT_OPTION;
Common::Array<Monster> &_monsterList;
void writeOptions();
@@ -89,6 +89,13 @@ private:
*/
void clearPartyArea();
+ /** Start of the main combat loop
+ */
+ void combatLoop();
+
+ void selectMonster();
+ void selectParty();
+ void loop1();
public:
Combat();
virtual ~Combat() {}
Commit: 08dbd972572946215354aefed2508611b9fac0bd
https://github.com/scummvm/scummvm/commit/08dbd972572946215354aefed2508611b9fac0bd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:12+01:00
Commit Message:
MM: MM1: Move just written combat loop stuff to common base class
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 47b9d04adb9..b1bc9fdd49b 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -27,6 +27,10 @@ namespace MM {
namespace MM1 {
namespace Game {
+Combat::Combat() : _monsterList(g_globals->_encounters._monsterList) {
+ clear();
+}
+
void Combat::clear() {
Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
@@ -177,6 +181,45 @@ void Combat::setupHandicap() {
_handicap4 = 0;
}
+
+void Combat::combatLoop() {
+ if (_monsterIndex != 0) {
+ selectParty();
+ } else {
+ selectMonster();
+ }
+}
+
+void Combat::selectMonster() {
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ // TODO
+ }
+
+ // TODO
+}
+
+void Combat::selectParty() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ int speed = c._speed._current;
+ if (speed && speed >= _handicap2) {
+ if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
+ // Character is enabled
+ _mode = SELECT_OPTION;
+ return;
+ }
+ }
+ }
+
+ loop1();
+}
+
+void Combat::loop1() {
+ // TODO
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 913f557bab8..7d89abe4947 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -34,6 +34,7 @@ namespace Game {
class Combat : public GameLogic {
protected:
+ Common::Array<Monster> &_monsterList;
int _monstersCount = 0;
Common::Array<Character *> _party;
Monster *_monsterP;
@@ -49,13 +50,21 @@ protected:
int _handicap1, _handicap2;
int _handicap3, _handicap4;
int _attackerVal;
+
enum Handicap {
HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
HANDICAP_MONSTER = 2
};
Handicap _handicap = HANDICAP_EVEN;
+ enum Mode {
+ SELECT_OPTION, FIGHT_WHICH
+ };
+ Mode _mode = SELECT_OPTION;
- Combat() { clear(); }
+ /**
+ * Constructor
+ */
+ Combat();
/**
* Clear all the combat variables
@@ -102,6 +111,18 @@ protected:
* Sets up the handicap for the encounter
*/
void setupHandicap();
+
+ /*------- combat execution ------*/
+
+ /**
+ * Start of the main combat loop
+ */
+ void combatLoop();
+
+ void selectMonster();
+ void selectParty();
+ void loop1();
+
};
} // namespace Game
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 767ef929a35..5a36cd6acf5 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -29,8 +29,7 @@ namespace MM {
namespace MM1 {
namespace Views {
-Combat::Combat() : TextView("Combat"),
- _monsterList(g_globals->_encounters._monsterList) {
+Combat::Combat() : TextView("Combat") {
}
bool Combat::msgFocus(const FocusMessage &msg) {
@@ -259,45 +258,6 @@ void Combat::clearPartyArea() {
clearLines(16, 18);
}
-void Combat::combatLoop() {
- if (_monsterIndex != 0) {
- selectParty();
- } else {
- selectMonster();
- }
-}
-
-void Combat::selectMonster() {
- for (uint i = 0; i < _monsterList.size(); ++i) {
- // TODO
- }
-
- // TODO
-}
-
-void Combat::selectParty() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- g_globals->_currCharacter = &c;
-
- int speed = c._speed._current;
- if (speed && speed >= _handicap2) {
- if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
- // Character is enabled
- _mode = SELECT_OPTION;
- return;
- }
- }
- }
-
- loop1();
-}
-
-void Combat::loop1() {
- // TODO
-}
-
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index bc679e83b26..19e3f7c0207 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -31,12 +31,6 @@ namespace Views {
class Combat : public TextView, public Game::Combat {
private:
- enum Mode {
- SELECT_OPTION, FIGHT_WHICH
- };
- Mode _mode = SELECT_OPTION;
- Common::Array<Monster> &_monsterList;
-
void writeOptions();
void writeAttackOptions();
void writeCastOption();
@@ -89,13 +83,6 @@ private:
*/
void clearPartyArea();
- /** Start of the main combat loop
- */
- void combatLoop();
-
- void selectMonster();
- void selectParty();
- void loop1();
public:
Combat();
virtual ~Combat() {}
Commit: 3209b6cc727a378af731f6bc329ffe11c0a5bb93
https://github.com/scummvm/scummvm/commit/3209b6cc727a378af731f6bc329ffe11c0a5bb93
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:12+01:00
Commit Message:
MM: MM1: Added combat proc1 method
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 07a16ecc406..51aad1701fc 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -126,6 +126,10 @@
ready:
1: " ARE YOU READY? "
2: "THEN PRESS ENTER!"
+ search:
+ search: "SEARCH: "
+ you_found: "YOU FOUND..."
+ nothing: "NOTHING"
statues:
stone: "ON THIS STONE STATUE OF "
plaque: "A PLAQUE READS..."
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 26a92f416b3..ab5753e529c 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -27,6 +27,8 @@
namespace MM {
namespace MM1 {
+#define TREASURE_COUNT 8
+
enum EnablementBit {
KNIGHT_BIT = 0x20, PALADIN_BIT = 0x10, ARCHER_BIT = 8,
CLERIC_BIT = 4, SORCERER_BIT = 2, ROBBER_BIT = 1,
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 9809b245e7e..8492f705ff9 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -44,9 +44,19 @@ bool Monsters::load() {
mon._field10 = getNextValue(line);
mon._field11 = getNextValue(line);
mon._field12 = getNextValue(line);
-
- for (int i = 0; i < 13; ++i)
- mon._unk[i] = getNextValue(line);
+ mon._field13 = getNextValue(line);
+ mon._field14 = getNextValue(line);
+ mon._field15 = getNextValue(line);
+ mon._field16 = getNextValue(line);
+ mon._field17 = getNextValue(line);
+ mon._field18 = getNextValue(line);
+ mon._field19 = getNextValue(line);
+ mon._field1a = getNextValue(line);
+ mon._field1b = getNextValue(line);
+ mon._field1c = getNextValue(line);
+ mon._field1d = getNextValue(line);
+ mon._field1e = getNextValue(line);
+ mon._field1f = getNextValue(line);
}
return true;
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index cabf42f9453..0ae50fca351 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -43,7 +43,18 @@ struct Monster {
byte _field10;
byte _field11;
byte _field12;
- byte _unk[12];
+ byte _field13;
+ byte _field14;
+ byte _field15;
+ byte _field16;
+ byte _field17;
+ byte _field18;
+ byte _field19;
+ byte _field1a;
+ byte _field1b;
+ byte _field1c;
+ byte _field1d;
+ byte _field1e;
byte _field1f;
};
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b1bc9fdd49b..c4a874160f6 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -38,6 +38,7 @@ void Combat::clear() {
Common::fill(&_canAttack[0], &_canAttack[6], false);
Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
+ _val6 = _val7 = 0;
_handicap1 = _handicap2 = 0;
_handicap3 = _handicap4 = 0;
_handicap = HANDICAP_EVEN;
@@ -191,8 +192,13 @@ void Combat::combatLoop() {
}
void Combat::selectMonster() {
+ _monsterP = &_monsterList[0];
+ monsterIndexOf();
+ int count = 0;
+
for (uint i = 0; i < _monsterList.size(); ++i) {
- // TODO
+ count += _monsterP->_field16;
+ proc1();
}
// TODO
@@ -220,6 +226,28 @@ void Combat::loop1() {
// TODO
}
+void Combat::proc1() {
+ _val7 = _monsterP->_field18;
+ _val6 = MAX(_val6, _val7);
+
+ if (_val7 & 1)
+ g_globals->_treasure[7] += getRandomNumber(1, 6);
+
+ if (_val7 & 6) {
+ if (!(_val7 & 2)) {
+ WRITE_LE_UINT16(&g_globals->_treasure[5],
+ READ_LE_UINT16(&g_globals->_treasure[5]) +
+ getRandomNumber(1, 10));
+ } else if (!(_val7 & 4)) {
+ WRITE_LE_UINT16(&g_globals->_treasure[5],
+ READ_LE_UINT16(&g_globals->_treasure[5]) +
+ getRandomNumber(1, 100));
+ } else {
+ g_globals->_treasure[6] += getRandomNumber(1, 4);
+ }
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 7d89abe4947..83109df836a 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -47,6 +47,7 @@ protected:
int _roundNum;
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
+ int _val6, _val7;
int _handicap1, _handicap2;
int _handicap3, _handicap4;
int _attackerVal;
@@ -122,7 +123,7 @@ protected:
void selectMonster();
void selectParty();
void loop1();
-
+ void proc1();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 2b78bd76070..742b9a5b8a6 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -31,7 +31,6 @@ namespace MM1 {
namespace Game {
ViewBase::ViewBase(UIElement *owner) : Views::TextView("View", owner) {
- Common::fill(&_arr2[0], &_arr2[8], 0);
}
void ViewBase::update() {
@@ -181,7 +180,8 @@ void ViewBase::forward(KeybindingAction action) {
}
}
- Common::fill(&_arr2[0], &_arr2[8], 0);
+ Common::fill(&g_globals->_treasure[0],
+ &g_globals->_treasure[TREASURE_COUNT], 0);
int maxVal = map[Maps::MAP_29];
if (g_engine->getRandomNumber(maxVal) == maxVal)
@@ -209,7 +209,8 @@ void ViewBase::backwards() {
}
}
- Common::fill(&_arr2[0], &_arr2[8], 0);
+ Common::fill(&g_globals->_treasure[0],
+ &g_globals->_treasure[TREASURE_COUNT], 0);
int maxVal = map[Maps::MAP_29];
if (g_engine->getRandomNumber(maxVal) == maxVal)
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 55b0b7be95c..1b29357f045 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -38,7 +38,6 @@ protected:
bool _isDark = false;
Common::String _dialogMessage;
int _businessDisplay = -1;
- byte _arr2[8];
bool _stepRandom = false;
private:
/**
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 91432d2f0b5..03a7f5a0a32 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -32,6 +32,7 @@ Globals *g_globals;
Globals::Globals() {
g_globals = this;
+ Common::fill(&_treasure[0], &_treasure[TREASURE_COUNT], 0);
}
Globals::~Globals() {
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 60feb0ff508..ee1f3233474 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -50,6 +50,7 @@ public:
bool _heardRumor = false;
Game::Encounter _encounters;
Monsters _monsters;
+ byte _treasure[TREASURE_COUNT];
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
Commit: f8432a39fb96e760804ed06010b663f8e07cacd5
https://github.com/scummvm/scummvm/commit/f8432a39fb96e760804ed06010b663f8e07cacd5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:12+01:00
Commit Message:
MM: MM1: Change getRandomNumber to be 1 based by default
Changed paths:
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/mm1.h
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 7782492d07e..215354c7827 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -344,7 +344,7 @@ SpellResult Spells::cleric54_removeCondition(Character *chr) {
SpellResult Spells::cleric55_restoreEnergy(Character *chr) {
if (chr->_level._current < chr->_level._base) {
chr->_level._current = MIN(
- chr->_level._current + g_engine->getRandomNumber(1, 5),
+ chr->_level._current + g_engine->getRandomNumber(5),
(int)chr->_level._base
);
return SR_SUCCESS_DONE;
@@ -378,7 +378,7 @@ SpellResult Spells::cleric62_raiseDead(Character *chr) {
SpellResult Spells::cleric63_rejuvinate(Character *chr) {
if (g_engine->getRandomNumber(100) < 75) {
- chr->_age._base = MIN(chr->_age._base - g_engine->getRandomNumber(1, 10),
+ chr->_age._base = MIN(chr->_age._base - g_engine->getRandomNumber(10),
200);
return SR_FAILED;
} else {
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index c4a874160f6..dc71fe85700 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -55,7 +55,7 @@ void Combat::loadArrays() {
for (uint i = 0; i < enc._monsterList.size(); ++i) {
Monster &mon = enc._monsterList[i];
- int val = getRandomNumber(1, 8);
+ int val = getRandomNumber(8);
mon._field11 += val;
_arr1[i] = mon._field11;
@@ -93,7 +93,7 @@ void Combat::setupCanAttacks() {
_canAttack[i] = true;
} else {
_canAttack[MAX_PARTY_SIZE - 1] =
- getRandomNumber(1, 100) <= 10;
+ getRandomNumber(100) <= 10;
}
}
@@ -110,11 +110,11 @@ void Combat::setupCanAttacks() {
if (g_globals->_party.size() > 3)
checkRightWall();
if (g_globals->_party.size() > 4) {
- if (_canAttack[2] && getRandomNumber(1, 100) <= 5)
+ if (_canAttack[2] && getRandomNumber(100) <= 5)
_canAttack[4] = true;
}
if (g_globals->_party.size() > 5) {
- if (_canAttack[3] && getRandomNumber(1, 100) <= 5)
+ if (_canAttack[3] && getRandomNumber(100) <= 5)
_canAttack[5] = true;
}
@@ -137,28 +137,28 @@ void Combat::setupAttackerVal() {
++_attackerVal;
}
- _attackerVal = getRandomNumber(1, _attackerVal + 1) - 1;
+ _attackerVal = getRandomNumber(_attackerVal + 1) - 1;
}
void Combat::checkLeftWall() {
Maps::Maps &maps = *g_maps;
_canAttack[2] = !(maps._currentWalls & maps._leftMask) ||
- getRandomNumber(1, 100) <= 25;
+ getRandomNumber(100) <= 25;
}
void Combat::checkRightWall() {
Maps::Maps &maps = *g_maps;
_canAttack[3] = !(maps._currentWalls & maps._rightMask) ||
- getRandomNumber(1, 100) <= 25;
+ getRandomNumber(100) <= 25;
}
void Combat::setupHandicap() {
_handicap2 = _handicap3 = 40;
- _handicap1 = getRandomNumber(1, 7);
+ _handicap1 = getRandomNumber(7);
- int val = getRandomNumber(1, 7);
+ int val = getRandomNumber(7);
if (val < _handicap1) {
SWAP(val, _handicap1);
_handicap4 = val - _handicap1;
@@ -231,19 +231,19 @@ void Combat::proc1() {
_val6 = MAX(_val6, _val7);
if (_val7 & 1)
- g_globals->_treasure[7] += getRandomNumber(1, 6);
+ g_globals->_treasure[7] += getRandomNumber(6);
if (_val7 & 6) {
if (!(_val7 & 2)) {
WRITE_LE_UINT16(&g_globals->_treasure[5],
READ_LE_UINT16(&g_globals->_treasure[5]) +
- getRandomNumber(1, 10));
+ getRandomNumber(10));
} else if (!(_val7 & 4)) {
WRITE_LE_UINT16(&g_globals->_treasure[5],
READ_LE_UINT16(&g_globals->_treasure[5]) +
- getRandomNumber(1, 100));
+ getRandomNumber(100));
} else {
- g_globals->_treasure[6] += getRandomNumber(1, 4);
+ g_globals->_treasure[6] += getRandomNumber(4);
}
}
}
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 43409791734..8a96bb464ed 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -65,7 +65,7 @@ void Encounter::execute() {
if (maxRand >= 2) {
int highestRand = map[Maps::MAP_33];
maxRand = MIN(maxRand, highestRand);
- comp = getRandomNumber(1, maxRand);
+ comp = getRandomNumber(maxRand);
} else {
comp = 1;
}
@@ -80,7 +80,7 @@ void Encounter::execute() {
_monsterNum16 = comp;
_levelIndex += comp;
- _monsterNum = getRandomNumber(1, 16);
+ _monsterNum = getRandomNumber(16);
_monsIndexes[_monsterIndex] = _monsterNum;
_monsterIndex = (_monsterIndex + 1) & 0xff;
@@ -89,7 +89,7 @@ void Encounter::execute() {
goto exit_loop;
monsterP = getMonster();
- maxVal = getRandomNumber(1, monsterP->_count);
+ maxVal = getRandomNumber(monsterP->_count);
for (int i = 0; i < maxVal; ++i) {
assert(_monsterIndex > 0);
@@ -115,7 +115,7 @@ exit_loop:
maxVal = (_arr1[i] - 1) * 16 + _monsIndexes[i];
if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
_arr1[i] = 10;
- _monsIndexes[i] = getRandomNumber(1, MAX_COMBAT_MONSTERS);
+ _monsIndexes[i] = getRandomNumber(MAX_COMBAT_MONSTERS);
}
// Add monster details to list
@@ -134,7 +134,7 @@ exit_loop:
}
void Encounter::randomAdjust() {
- int rval = getRandomNumber(1, 100);
+ int rval = getRandomNumber(100);
_levelOffset = 0;
if (rval < 51) {
@@ -154,7 +154,7 @@ const Monster *Encounter::getMonster() {
}
bool Encounter::checkSurroundParty() const {
- return getRandomNumber(1, 100) > _fleeThreshold;
+ return getRandomNumber(100) > _fleeThreshold;
}
void Encounter::changeCharAlignment(Alignment align) {
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index 5a881f13eb9..a0943d83b7f 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -60,7 +60,7 @@ public:
return _randomSource.getRandomNumber(maxNumber - minNumber + 1) + minNumber;
}
int getRandomNumber(int maxNumber) {
- return _randomSource.getRandomNumber(maxNumber);
+ return getRandomNumber(1, maxNumber - 1);
}
Common::String getTargetName() const {
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 84ce5d6a04c..56f3f080c93 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -161,10 +161,10 @@ void Encounter::timeout() {
_mode = SURPRISED_BY_MONSTERS;
} else if (enc._encounterType == Game::NORMAL_SURPRISED ||
/* ENCOUNTER_OPTIONS */
- g_engine->getRandomNumber(1, 100) > map[Maps::MAP_21]) {
+ g_engine->getRandomNumber(100) > map[Maps::MAP_21]) {
// Potentially surprised. Check for guard dog spell
if (g_globals->_spells._s.guard_dog ||
- g_engine->getRandomNumber(1, 100) > map[Maps::MAP_20])
+ g_engine->getRandomNumber(100) > map[Maps::MAP_20])
_mode = ENCOUNTER_OPTIONS;
else
_mode = SURPRISED_BY_MONSTERS;
@@ -219,7 +219,7 @@ bool Encounter::msgKeypress(const KeypressMessage &msg) {
case BRIBE:
if (msg.keycode == Common::KEYCODE_y) {
- if (getRandomNumber(1, 100) > map[Maps::MAP_BRIBE_THRESHOLD]) {
+ if (getRandomNumber(100) > map[Maps::MAP_BRIBE_THRESHOLD]) {
_mode = NOT_ENOUGH;
redraw();
} else {
@@ -277,14 +277,14 @@ void Encounter::bribe() {
_mode = NO_RESPONSE;
redraw();
- } else if (getRandomNumber(1, 7) == 5 && !enc._bribeFleeCtr) {
+ } else if (getRandomNumber(7) == 5 && !enc._bribeFleeCtr) {
// Rare chance to abort combat immediately
encounterEnded();
} else {
_mode = BRIBE;
- int val = getRandomNumber(1, 100);
+ int val = getRandomNumber(100);
if (val < 6) {
_bribeType = BRIBE_GEMS;
_bribeTypeStr = STRING["dialogs.encounter.gems"];
@@ -303,7 +303,7 @@ void Encounter::bribe() {
void Encounter::retreat() {
const Maps::Map &map = *g_maps->_currentMap;
const Game::Encounter &enc = g_globals->_encounters;
- int val = getRandomNumber(1, 110);
+ int val = getRandomNumber(110);
if (val >= 100) {
// 9% chance of simply fleeing
@@ -326,8 +326,8 @@ void Encounter::surrender() {
const Game::Encounter &enc = g_globals->_encounters;
const Maps::Map &map = *g_maps->_currentMap;
- if (getRandomNumber(1, 100) > map[Maps::MAP_SURRENDER_THRESHOLD] ||
- getRandomNumber(1, 100) > enc._fleeThreshold) {
+ if (getRandomNumber(100) > map[Maps::MAP_SURRENDER_THRESHOLD] ||
+ getRandomNumber(100) > enc._fleeThreshold) {
_mode = SURRENDER_FAILED;
redraw();
} else {
@@ -335,7 +335,7 @@ void Encounter::surrender() {
g_maps->_mapPos.y = map[Maps::MAP_SURRENDER_Y];
// Randomly remove food, gems, or gold from the party
- int val = getRandomNumber(1, 200);
+ int val = getRandomNumber(200);
if (val < 51) {
} else if (val < 151) {
g_globals->_party.clearPartyGold();
Commit: e26dff189e92086834288ae00c6efd222f129f56
https://github.com/scummvm/scummvm/commit/e26dff189e92086834288ae00c6efd222f129f56
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:12+01:00
Commit Message:
MM: MM1: In progress adding selectMonster method
Changed paths:
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index dc71fe85700..fd67eba71d7 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -192,15 +192,22 @@ void Combat::combatLoop() {
}
void Combat::selectMonster() {
- _monsterP = &_monsterList[0];
- monsterIndexOf();
int count = 0;
+ int activeCharCount = 0;
for (uint i = 0; i < _monsterList.size(); ++i) {
+ _monsterP = &_monsterList[i];
+ monsterIndexOf();
+
count += _monsterP->_field16;
proc1();
}
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (!(g_globals->_party[i]._condition & BAD_CONDITION))
+ ++activeCharCount;
+ }
+
// TODO
}
Commit: d1b80934e4e4832376443ce85fa2d4ae12d56076
https://github.com/scummvm/scummvm/commit/d1b80934e4e4832376443ce85fa2d4ae12d56076
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:12+01:00
Commit Message:
MM: MM1: gcc compilation fixes
Changed paths:
engines/mm/mm1/data/party.cpp
engines/mm/mm1/game/rest.cpp
engines/mm/mm1/views/character_base.cpp
engines/mm/mm1/views/characters.cpp
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/spells/teleport.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index f4933797cde..9a203067015 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -47,6 +47,8 @@ void Party::share(TransferKind shareType) {
case TK_FOOD:
SHARE_FIELD(_food);
break;
+ default:
+ break;
}
}
diff --git a/engines/mm/mm1/game/rest.cpp b/engines/mm/mm1/game/rest.cpp
index 4336987a116..aeb7fcee12e 100644
--- a/engines/mm/mm1/game/rest.cpp
+++ b/engines/mm/mm1/game/rest.cpp
@@ -42,7 +42,7 @@ void Rest::check() {
g_globals->_party.size() - 1);
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- if (c._condition >= 0 && i != awakeIndex)
+ if (!(c._condition & BAD_CONDITION) && i != awakeIndex)
c._condition |= ASLEEP;
}
diff --git a/engines/mm/mm1/views/character_base.cpp b/engines/mm/mm1/views/character_base.cpp
index 2fd99a6138c..a56712d1ada 100644
--- a/engines/mm/mm1/views/character_base.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -148,7 +148,7 @@ void CharacterBase::printInventory() {
_textPos.x++;
if (re._equipped[i])
writeString(STRING[Common::String::format("stats.items.%d",
- re._equipped[i])]);
+ (int)re._equipped[i]._id)]);
// Backpack item
writeChar(20, 13 + i, 'A' + i);
@@ -156,7 +156,7 @@ void CharacterBase::printInventory() {
_textPos.x++;
if (re._backpack[i])
writeString(STRING[Common::String::format("stats.items.%d",
- re._backpack[i])]);
+ (int)re._backpack[i]._id)]);
}
}
diff --git a/engines/mm/mm1/views/characters.cpp b/engines/mm/mm1/views/characters.cpp
index 1ae9dd3fe7c..bc8eeb07b6b 100644
--- a/engines/mm/mm1/views/characters.cpp
+++ b/engines/mm/mm1/views/characters.cpp
@@ -49,7 +49,7 @@ void Characters::draw() {
pad_string(charName, 16, '.');
Common::String level = Common::String::format("(%d)L%d",
- roster._towns[charNum], re._level);
+ roster._towns[charNum], re._level._current);
pad_string(level, 7);
Common::String className = (re._class >= KNIGHT && re._class <= ROBBER) ?
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 56f3f080c93..2ddb1b499dd 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -312,7 +312,7 @@ void Encounter::retreat() {
// Nowhere to run depending on the map
_mode = NOWHERE_TO_RUN;
redraw();
- } else if (enc._monsterList.size() < (int)g_globals->_party.size() || !enc.checkSurroundParty()) {
+ } else if (enc._monsterList.size() < g_globals->_party.size() || !enc.checkSurroundParty()) {
// Only allow fleeing if the number of monsters
// are less than the size of the party
flee();
diff --git a/engines/mm/mm1/views/spells/teleport.cpp b/engines/mm/mm1/views/spells/teleport.cpp
index 000071f4f8c..c3605fd522a 100644
--- a/engines/mm/mm1/views/spells/teleport.cpp
+++ b/engines/mm/mm1/views/spells/teleport.cpp
@@ -81,7 +81,7 @@ bool Teleport::msgKeypress(const KeypressMessage &msg) {
_mode = CAST;
redraw();
- } else if (_mode == CAST && Common::KEYCODE_RETURN) {
+ } else if (_mode == CAST && msg.keycode == Common::KEYCODE_RETURN) {
teleport();
}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 7e18616a745..b8b80e91b35 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -73,7 +73,6 @@ MODULE_OBJS := \
mm1/views/protect.o \
mm1/views/quick_ref.o \
mm1/views/rest.o \
- mm1/views/statue.o \
mm1/views/title.o \
mm1/views/text_entry.o \
mm1/views/text_view.o \
Commit: fa32e5623ec9b02dc35e9ec19c71d41b2984f579
https://github.com/scummvm/scummvm/commit/fa32e5623ec9b02dc35e9ec19c71d41b2984f579
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:12+01:00
Commit Message:
MM: MM1: More gcc compilation fixes
Changed paths:
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/views_enh/locations/temple.cpp
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index e1b33a90bb4..6079737d2f3 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -194,6 +194,8 @@ void Map00::special08() {
maps._mapPos = Common::Point(8, 5);
g_events->send("View", GameMessage("UPDATE"));
break;
+ default:
+ break;
}
}
);
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 6883ba14930..40d22e72383 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -261,6 +261,8 @@ void Maps::loadTown(TownId townId) {
_mapPos = Common::Point(4, 4);
display(0xB1A);
break;
+ default:
+ break;
}
_currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x] = true;
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
index 22e6d45d666..28a6e2aba14 100644
--- a/engines/mm/mm1/views_enh/locations/temple.cpp
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/views_enh/locations/Temple.h"
+#include "mm/mm1/views_enh/locations/temple.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
Commit: 84ccae5c7604dc48923239f467d4a07dcfc76cc0
https://github.com/scummvm/scummvm/commit/84ccae5c7604dc48923239f467d4a07dcfc76cc0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:13+01:00
Commit Message:
MM: MM1: Added selectTreasure methods
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index fd67eba71d7..191c2f96b13 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -37,6 +37,8 @@ void Combat::clear() {
Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
+ Common::fill(&_treasureFlags[0], &_treasureFlags[MAX_PARTY_SIZE], false);
+
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_val6 = _val7 = 0;
_handicap1 = _handicap2 = 0;
@@ -187,11 +189,29 @@ void Combat::combatLoop() {
if (_monsterIndex != 0) {
selectParty();
} else {
- selectMonster();
+ defeatedMonster();
+ }
+}
+
+void Combat::selectParty() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ int speed = c._speed._current;
+ if (speed && speed >= _handicap2) {
+ if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
+ // Character is enabled
+ _mode = SELECT_OPTION;
+ return;
+ }
+ }
}
+
+ loop1();
}
-void Combat::selectMonster() {
+void Combat::defeatedMonster() {
int count = 0;
int activeCharCount = 0;
@@ -208,25 +228,9 @@ void Combat::selectMonster() {
++activeCharCount;
}
- // TODO
-}
-
-void Combat::selectParty() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- g_globals->_currCharacter = &c;
+ shareSplit();
- int speed = c._speed._current;
- if (speed && speed >= _handicap2) {
- if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
- // Character is enabled
- _mode = SELECT_OPTION;
- return;
- }
- }
- }
-
- loop1();
+ // TODO
}
void Combat::loop1() {
@@ -255,6 +259,65 @@ void Combat::proc1() {
}
}
+void Combat::shareSplit() {
+
+}
+
+#define SHIFT_BIT (_val6 & 0x80) != 0; _val6 <<= 1
+
+void Combat::selectTreasure() {
+ for (int i = 0; i < 5; ++i) {
+ bool flag = SHIFT_BIT;
+ if (flag && getRandomNumber(100) <= (10 + i * 10))
+ selectTreasure2(5 - i);
+ }
+
+ auto &treasure = g_globals->_treasure;
+ treasure[0] = 0;
+
+ if (_treasureFlags[4]) {
+ treasure[1] = 10;
+ } else if (_treasureFlags[3]) {
+ treasure[1] = 5 + getRandomNumber(4);
+ } else if (_treasureFlags[2]) {
+ treasure[1] = 4 + getRandomNumber(4);
+ } else if (_treasureFlags[1]) {
+ treasure[1] = 3 + getRandomNumber(4);
+ } else if (_treasureFlags[0] || treasure[7]) {
+ treasure[1] = 1 + getRandomNumber(4);
+ } else if (treasure[6]) {
+ treasure[1] = getRandomNumber(4) - 1;
+ } else {
+ treasure[1] = getRandomNumber(2) - 1;
+ }
+}
+
+void Combat::selectTreasure2(int count) {
+ static const byte TREASURES_ARR1[6] = { 1, 61, 86, 121, 156, 171 };
+ static const byte TREASURES_ARR2[6] = { 12, 5, 7, 7, 3, 12 };
+ byte val1, val2;
+ int idx;
+
+ _treasureFlags[count - 1] = true;
+
+ idx = getRandomNumber(0, 5);
+ val1 = TREASURES_ARR1[idx];
+ val2 = TREASURES_ARR2[idx];
+
+ for (idx = 0; idx < count; ++idx)
+ _val1 += _val2;
+
+ _val1 += getRandomNumber(_val2) - 1;
+
+ auto &treasure = g_globals->_treasure;
+ if (!treasure[2])
+ treasure[2] = _val1;
+ else if (!treasure[3])
+ treasure[3] = _val1;
+ else if (!treasure[4])
+ treasure[4] = _val1;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 83109df836a..ce0c3c17d6f 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -43,11 +43,12 @@ protected:
byte _monsterStatus[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
int _arr3[MAX_PARTY_SIZE / 2];
+ bool _treasureFlags[MAX_PARTY_SIZE];
int _val1;
int _roundNum;
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
- int _val6, _val7;
+ byte _val6, _val7;
int _handicap1, _handicap2;
int _handicap3, _handicap4;
int _attackerVal;
@@ -58,7 +59,7 @@ protected:
};
Handicap _handicap = HANDICAP_EVEN;
enum Mode {
- SELECT_OPTION, FIGHT_WHICH
+ SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTER
};
Mode _mode = SELECT_OPTION;
@@ -120,10 +121,17 @@ protected:
*/
void combatLoop();
- void selectMonster();
+ void defeatedMonster();
void selectParty();
void loop1();
void proc1();
+ void shareSplit();
+
+ /**
+ * Select treasure for a defeated monster
+ */
+ void selectTreasure();
+ void selectTreasure2(int index);
};
} // namespace Game
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 5a36cd6acf5..cdfa2135ab6 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -65,6 +65,9 @@ void Combat::draw() {
case SELECT_OPTION:
writeOptions();
break;
+ case DEFEATED_MONSTER:
+
+
default:
break;
}
Commit: e858af9196037e78062dde1bfef357cd29d28574
https://github.com/scummvm/scummvm/commit/e858af9196037e78062dde1bfef357cd29d28574
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:13+01:00
Commit Message:
MM: MM1: Adding rendering for monsters being defeated
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 51aad1701fc..9e2d79f4772 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -309,6 +309,9 @@
monster_plus: "MONSTER +"
and_goes_down: "AND GOES DOWN!!!"
dies: "DIES!"
+ defeating1: "! FOR DEFEATING THE MONSTERS !"
+ defeating2: "! EACH SURVIVOR RECEIVES !"
+ xp: "EXPERIENCE POINTS."
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 8492f705ff9..4aa24ee2192 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -47,8 +47,7 @@ bool Monsters::load() {
mon._field13 = getNextValue(line);
mon._field14 = getNextValue(line);
mon._field15 = getNextValue(line);
- mon._field16 = getNextValue(line);
- mon._field17 = getNextValue(line);
+ mon._experience = getNextValue(line);
mon._field18 = getNextValue(line);
mon._field19 = getNextValue(line);
mon._field1a = getNextValue(line);
@@ -62,7 +61,7 @@ bool Monsters::load() {
return true;
}
-byte Monsters::getNextValue(Common::String &line) {
+uint Monsters::getNextValue(Common::String &line) {
// Verify the next comma
if (!line.hasPrefix(", "))
return 0;
@@ -70,7 +69,7 @@ byte Monsters::getNextValue(Common::String &line) {
line.deleteChar(0);
// Get the value
- byte result = atoi(line.c_str());
+ int result = atoi(line.c_str());
while (!line.empty() && Common::isDigit(line.firstChar()))
line.deleteChar(0);
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 0ae50fca351..1c8743b69e1 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -46,8 +46,7 @@ struct Monster {
byte _field13;
byte _field14;
byte _field15;
- byte _field16;
- byte _field17;
+ uint16 _experience;
byte _field18;
byte _field19;
byte _field1a;
@@ -66,7 +65,7 @@ private:
/**
* Get the next value from a read line
*/
- byte getNextValue(Common::String &line);
+ uint getNextValue(Common::String &line);
public:
Monsters() : _monPix(MONPIX_DTA) {}
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 191c2f96b13..2388c594815 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -47,6 +47,8 @@ void Combat::clear() {
_monsterP = nullptr;
_monsterIndex = _currentChar = 0;
_attackerVal = 0;
+ _totalExperience = 0;
+
// TODO: clear everything
_roundNum = 1;
@@ -189,7 +191,7 @@ void Combat::combatLoop() {
if (_monsterIndex != 0) {
selectParty();
} else {
- defeatedMonster();
+ defeatedMonsters();
}
}
@@ -211,15 +213,15 @@ void Combat::selectParty() {
loop1();
}
-void Combat::defeatedMonster() {
- int count = 0;
+void Combat::defeatedMonsters() {
int activeCharCount = 0;
+ _totalExperience = 0;
for (uint i = 0; i < _monsterList.size(); ++i) {
_monsterP = &_monsterList[i];
monsterIndexOf();
- count += _monsterP->_field16;
+ _totalExperience += _monsterP->_experience;
proc1();
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index ce0c3c17d6f..d6ba5c578c5 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -52,6 +52,7 @@ protected:
int _handicap1, _handicap2;
int _handicap3, _handicap4;
int _attackerVal;
+ int _totalExperience;
enum Handicap {
HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
@@ -59,7 +60,7 @@ protected:
};
Handicap _handicap = HANDICAP_EVEN;
enum Mode {
- SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTER
+ SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS
};
Mode _mode = SELECT_OPTION;
@@ -121,7 +122,7 @@ protected:
*/
void combatLoop();
- void defeatedMonster();
+ void defeatedMonsters();
void selectParty();
void loop1();
void proc1();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index cdfa2135ab6..9ec2b927762 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -65,8 +65,11 @@ void Combat::draw() {
case SELECT_OPTION:
writeOptions();
break;
- case DEFEATED_MONSTER:
+ case DEFEATED_MONSTERS:
+ writeDefeat();
+ delaySeconds(3);
+ break;
default:
break;
@@ -261,6 +264,22 @@ void Combat::clearPartyArea() {
clearLines(16, 18);
}
+void Combat::writeDefeat() {
+ resetBottom();
+ writeString(10, 0, "+----------------------------+");
+ for (int y = 1; y < 8; ++y) {
+ writeChar(10, y, '!');
+ writeChar(37, y, '!');
+ }
+ writeString(10, 0, "+----------------------------+");
+
+ writeString(10, 2, STRING["dialogs.combat.defeating1"]);
+ writeString(10, 4, STRING["dialogs.combat.defeating1"]);
+ writeNumber(14, 6, _totalExperience);
+ _textPos.x++;
+ writeString(STRING["dialogs.combat.xp"]);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 19e3f7c0207..cf4b15b9837 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -83,6 +83,8 @@ private:
*/
void clearPartyArea();
+ void writeDefeat();
+
public:
Combat();
virtual ~Combat() {}
Commit: d5b6d96a703334b14642708b9deb7bbabc47c934
https://github.com/scummvm/scummvm/commit/d5b6d96a703334b14642708b9deb7bbabc47c934
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:13+01:00
Commit Message:
MM: MM1: Finished remainder of monsters defeated combat end
Changed paths:
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 9a203067015..0de5126b23d 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -80,5 +80,16 @@ void Party::updateAC() {
(*this)[i].updateAC();
}
+void Party::combatDone() {
+ for (uint i = 0; i < size(); ++i) {
+ Character &c = (*this)[i];
+ c.updateAttributes();
+ c.update58();
+
+ if (!(c._condition & BAD_CONDITION))
+ c._condition &= ~(ASLEEP | SILENCED);
+ }
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index 1bc89b1fe74..ad6445cf986 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -60,6 +60,11 @@ struct Party : public Common::Array<Character> {
* Update the entire party AC
*/
void updateAC();
+
+ /**
+ * Called to update the party after combat is done
+ */
+ void combatDone();
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 2388c594815..435a443c270 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -217,6 +217,7 @@ void Combat::defeatedMonsters() {
int activeCharCount = 0;
_totalExperience = 0;
+ // Count total experience from all defeated monsters
for (uint i = 0; i < _monsterList.size(); ++i) {
_monsterP = &_monsterList[i];
monsterIndexOf();
@@ -225,12 +226,21 @@ void Combat::defeatedMonsters() {
proc1();
}
+ // Count number of active characters
for (uint i = 0; i < g_globals->_party.size(); ++i) {
if (!(g_globals->_party[i]._condition & BAD_CONDITION))
++activeCharCount;
}
- shareSplit();
+ // Split the experience between the active characters
+ _totalExperience /= activeCharCount;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (!(g_globals->_party[i]._condition & BAD_CONDITION))
+ g_globals->_party[i]._exp += _totalExperience;
+ }
+
+ // Update the party's characters
+ g_globals->_party.combatDone();
// TODO
}
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 9ec2b927762..1a7f8cbdf10 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -68,6 +68,7 @@ void Combat::draw() {
case DEFEATED_MONSTERS:
writeDefeat();
+ Sound::sound2(SOUND_3);
delaySeconds(3);
break;
@@ -77,6 +78,22 @@ void Combat::draw() {
}
void Combat::timeout() {
+ switch (_mode) {
+ case DEFEATED_MONSTERS: {
+ auto &spells = g_globals->_spells;
+ spells._s.bless = 0;
+ spells._s.invisbility = 0;
+ spells._s.shield = 0;
+ spells._s.power_shield = 0;
+
+ close();
+ g_events->send("Game", GameMessage("UPDATE"));
+ return;
+ }
+ default:
+ break;
+ }
+
redraw();
}
Commit: 295461b2e6875f1e9981c560fa2e38fced2db7f3
https://github.com/scummvm/scummvm/commit/295461b2e6875f1e9981c560fa2e38fced2db7f3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:13+01:00
Commit Message:
MM: MM1: In progress support methods for next round code
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/encounter.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 435a443c270..19370be5ea7 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -34,13 +34,15 @@ Combat::Combat() : _monsterList(g_globals->_encounters._monsterList) {
void Combat::clear() {
Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
+ Common::fill(&_arr4[0], &_arr4[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
- Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
Common::fill(&_treasureFlags[0], &_treasureFlags[MAX_PARTY_SIZE], false);
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_val6 = _val7 = 0;
+ _val8 = 0;
_handicap1 = _handicap2 = 0;
_handicap3 = _handicap4 = 0;
_handicap = HANDICAP_EVEN;
@@ -271,18 +273,14 @@ void Combat::proc1() {
}
}
-void Combat::shareSplit() {
-
-}
-
-#define SHIFT_BIT (_val6 & 0x80) != 0; _val6 <<= 1
-
void Combat::selectTreasure() {
+#define SHIFT_BIT (_val6 & 0x80) != 0; _val6 <<= 1
for (int i = 0; i < 5; ++i) {
bool flag = SHIFT_BIT;
if (flag && getRandomNumber(100) <= (10 + i * 10))
selectTreasure2(5 - i);
}
+#undef SHIFT_BIT
auto &treasure = g_globals->_treasure;
treasure[0] = 0;
@@ -330,6 +328,36 @@ void Combat::selectTreasure2(int count) {
treasure[4] = _val1;
}
+void Combat::nextRound() {
+ ++_roundNum;
+ setupHandicap();
+ clearArrays();
+ g_globals->_party.updateAC();
+
+ _val8 = getRandomNumber(g_globals->_party.size());
+
+}
+
+void Combat::clearArrays() {
+ Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE], 0);
+ Common::fill(&_arr4[0], &_arr4[MAX_COMBAT_MONSTERS], 0);
+}
+
+void Combat::updateHighestLevel() {
+ Encounter &enc = g_globals->_encounters;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ // This looks suspect, since it doesn't find the
+ // max of the party's active characters, just ends
+ // up set to whichever last character's level
+ if (!(c._condition & (ASLEEP | BLINDED | SILENCED | DISEASED | POISONED)))
+ enc._highestLevel = c._level._base;
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index d6ba5c578c5..2c32d8dfc08 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -40,15 +40,17 @@ protected:
Monster *_monsterP;
byte _arr1[MAX_COMBAT_MONSTERS];
byte _arr2[MAX_COMBAT_MONSTERS];
+ int _arr3[MAX_PARTY_SIZE / 2];
+ byte _arr4[MAX_COMBAT_MONSTERS];
byte _monsterStatus[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
- int _arr3[MAX_PARTY_SIZE / 2];
bool _treasureFlags[MAX_PARTY_SIZE];
int _val1;
int _roundNum;
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
byte _val6, _val7;
+ int _val8;
int _handicap1, _handicap2;
int _handicap3, _handicap4;
int _attackerVal;
@@ -122,17 +124,28 @@ protected:
*/
void combatLoop();
- void defeatedMonsters();
- void selectParty();
- void loop1();
- void proc1();
- void shareSplit();
-
/**
* Select treasure for a defeated monster
*/
void selectTreasure();
void selectTreasure2(int index);
+
+ /**
+ * Moves to the next round
+ */
+ void nextRound();
+
+ /**
+ * Update the _highestLevel to the remaining
+ * active members of the party
+ */
+ void updateHighestLevel();
+
+ void defeatedMonsters();
+ void selectParty();
+ void loop1();
+ void proc1();
+ void clearArrays();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index df8844c6126..d53ca7aebcf 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -43,7 +43,7 @@ private:
int _levelIndex = 0, _levelOffset = 0;
int _val9 = 0;
int _monsterNum16 = 0;
- int _totalLevels = 0, _highestLevel = 0;
+ int _totalLevels = 0;
int _monsterNum = 0;
byte _arr1[MAX_COMBAT_MONSTERS];
byte _monsIndexes[MAX_COMBAT_MONSTERS];
@@ -56,6 +56,7 @@ public:
int _alignmentsChanged = 0;
int _monsterImgNum = 0;
int _monsterIndex = 0;
+ int _highestLevel = 0;
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
public:
Commit: 9227a57ee50680509815e0a41a4460e203949e70
https://github.com/scummvm/scummvm/commit/9227a57ee50680509815e0a41a4460e203949e70
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:13+01:00
Commit Message:
MM: MM1: Added monsterChanges method
Changed paths:
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 1c8743b69e1..9f66b7740c0 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -37,6 +37,10 @@ enum MonsterStatus {
MON_BLINDED = 6, MON_AFRAID = 7, MON_DEAD = 8
};
+enum Field1E {
+ FIELD1E_40 = 0x40
+};
+
struct Monster {
Common::String _name; // char _name[15];
byte _count;
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 19370be5ea7..717bae03509 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -42,7 +42,8 @@ void Combat::clear() {
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_val6 = _val7 = 0;
- _val8 = 0;
+ _val8 = _val9 = 0;
+ _advanceIndex = 0;
_handicap1 = _handicap2 = 0;
_handicap3 = _handicap4 = 0;
_handicap = HANDICAP_EVEN;
@@ -50,6 +51,8 @@ void Combat::clear() {
_monsterIndex = _currentChar = 0;
_attackerVal = 0;
_totalExperience = 0;
+ _advanceIndex = 0;
+ _monstersResistSpells = _monstersRegenerate = false;
// TODO: clear everything
@@ -335,7 +338,27 @@ void Combat::nextRound() {
g_globals->_party.updateAC();
_val8 = getRandomNumber(g_globals->_party.size());
+ updateHighestLevel();
+ setMode(NEXT_ROUND);
+}
+
+void Combat::nextRound2() {
+ if (moveMonsters()) {
+ // Display that a monster advanced in the view
+ setMode(MONSTER_ADVANCES);
+ } else {
+ // No advancements, so move to next part of new round
+ nextRound3();
+ }
+}
+
+void Combat::nextRound3() {
+ if (monsterChanges()) {
+ setMode(MONSTERS_AFFECTED);
+ } else {
+ combatLoop();
+ }
}
void Combat::clearArrays() {
@@ -358,6 +381,104 @@ void Combat::updateHighestLevel() {
}
}
+bool Combat::moveMonsters() {
+ if (_attackerVal >= (int)_monsterList.size())
+ return false;
+
+ bool hasAdvance = false;
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ _advanceIndex = i;
+
+ if (!(_monsterStatus[i] & ~MON_MINDLESS) &&
+ _monsterList[i]._field1e & 0x80) {
+ monsterAdvances();
+ hasAdvance = true;
+ }
+ }
+
+ return hasAdvance;
+}
+
+void Combat::monsterAdvances() {
+ // TODO: Shouldn't placement changes affect the arrays
+ _monsterList.remove_at(_advanceIndex);
+ _advancingMonster = _monsterList[_advanceIndex]._name;
+}
+
+bool Combat::monsterChanges() {
+ _monstersRegenerate = _monstersResistSpells = false;
+
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ monsterSetPtr(i);
+
+ if ((_monsterP->_field1e & FIELD1E_40) &&
+ (_monsterP->_field11 != _arr1[i])) {
+ _monstersRegenerate = true;
+ int newVal = _arr1[i] + 5;
+ _arr1[i] = (byte)newVal;
+
+ if (newVal >= 256 || newVal >= _monsterP->_field11) {
+ _arr1[i] = _monsterP->_field11;
+ }
+ }
+
+ if (_monsterStatus[i]) {
+ proc2();
+
+ if (_val9) {
+ _monstersResistSpells = true;
+ byte v = _monsterStatus[i];
+
+ v &= 0x7f;
+ if (v != _monsterStatus[i]) {
+ _monsterStatus[i] = v;
+ } else {
+ v &= 0x3f;
+ if (v != _monsterStatus[i]) {
+ _monsterStatus[i] = v;
+ } else {
+ v &= 0x1f;
+ if (v != _monsterStatus[i]) {
+ _monsterStatus[i] = v;
+ } else {
+ v &= 0xf;
+ if (v != _monsterStatus[i]) {
+ _monsterStatus[i] = v;
+ } else {
+ v &= 7;
+ if (v != _monsterStatus[i]) {
+ _monsterStatus[i] = v;
+ } else {
+ v &= 3;
+ if (v != _monsterStatus[i]) {
+ _monsterStatus[i] = v;
+ } else {
+ v &= 1;
+ if (v != _monsterStatus[i])
+ _monsterStatus[i] = v;
+ else
+ _monsterStatus[i] = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ return _monstersRegenerate || _monstersResistSpells;
+}
+
+void Combat::proc2() {
+ int threshold = getMonsterIndex() * 8 + 20;
+ int val = getRandomNumber(100);
+
+ _val9 = (val != 100 && val <= threshold) ? 1 : 0;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 2c32d8dfc08..1731d8cff27 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -50,19 +50,23 @@ protected:
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
byte _val6, _val7;
- int _val8;
+ int _val8, _val9;
+ int _advanceIndex;
int _handicap1, _handicap2;
int _handicap3, _handicap4;
int _attackerVal;
int _totalExperience;
-
+ Common::String _advancingMonster;
+ bool _monstersResistSpells;
+ bool _monstersRegenerate;
enum Handicap {
HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
HANDICAP_MONSTER = 2
};
Handicap _handicap = HANDICAP_EVEN;
enum Mode {
- SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS
+ SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
+ NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
};
Mode _mode = SELECT_OPTION;
@@ -71,6 +75,8 @@ protected:
*/
Combat();
+ virtual void setMode(Mode newMode) = 0;
+
/**
* Clear all the combat variables
*/
@@ -124,6 +130,13 @@ protected:
*/
void combatLoop();
+ /**
+ * Get the monster index
+ */
+ int getMonsterIndex() const {
+ return _monsterIndex;
+ }
+
/**
* Select treasure for a defeated monster
*/
@@ -134,6 +147,8 @@ protected:
* Moves to the next round
*/
void nextRound();
+ void nextRound2();
+ void nextRound3();
/**
* Update the _highestLevel to the remaining
@@ -146,6 +161,10 @@ protected:
void loop1();
void proc1();
void clearArrays();
+ bool moveMonsters();
+ void monsterAdvances();
+ bool monsterChanges();
+ void proc2();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index d53ca7aebcf..734ca374809 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -55,7 +55,7 @@ public:
int _bribeAlignmentCtr = 0, _bribeFleeCtr = 0;
int _alignmentsChanged = 0;
int _monsterImgNum = 0;
- int _monsterIndex = 0;
+ int _monsterIndex = 0; // == _monsterList.size()
int _highestLevel = 0;
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 1a7f8cbdf10..6a18bfcabb4 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -32,6 +32,11 @@ namespace Views {
Combat::Combat() : TextView("Combat") {
}
+void Combat::setMode(Mode newMode) {
+ _mode = newMode;
+ redraw();
+}
+
bool Combat::msgFocus(const FocusMessage &msg) {
// Clear combat data
clear();
@@ -51,7 +56,24 @@ bool Combat::msgFocus(const FocusMessage &msg) {
}
void Combat::draw() {
- //Game::Encounter &enc = g_globals->_encounters;
+ switch (_mode) {
+ case NEXT_ROUND:
+ resetBottom();
+ highlightNextRound();
+ delaySeconds(1);
+ return;
+ case MONSTER_ADVANCES:
+ writeString(0, 20, _advancingMonster);
+ writeString(STRING["dialogs.combat.advances"]);
+ writeSpaces(30);
+ writeRound();
+ writeMonsters();
+ delaySeconds(2);
+ return;
+ default:
+ break;
+ }
+
clearSurface();
writeStaticContent();
@@ -79,6 +101,15 @@ void Combat::draw() {
void Combat::timeout() {
switch (_mode) {
+ case NEXT_ROUND:
+ nextRound2();
+ break;
+ case MONSTER_ADVANCES:
+ nextRound3();
+ break;
+ case MONSTERS_AFFECTED:
+ combatLoop();
+ break;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_spells;
spells._s.bless = 0;
@@ -297,6 +328,17 @@ void Combat::writeDefeat() {
writeString(STRING["dialogs.combat.xp"]);
}
+void Combat::highlightNextRound() {
+ Common::String s = Common::String::format("%s%d",
+ STRING["dialogs.combat.round"].c_str(),
+ _roundNum);
+
+ for (uint i = 0; i < s.size(); ++i)
+ s.setChar(s[i] | 0x80, i);
+
+ writeString(0, 1, s);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index cf4b15b9837..aef99d9462c 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -85,6 +85,16 @@ private:
void writeDefeat();
+ /**
+ * Highlight the round number indicator
+ */
+ void highlightNextRound();
+
+protected:
+ /**
+ * Sets a new display mode
+ */
+ void setMode(Mode newMode) override;
public:
Combat();
virtual ~Combat() {}
Commit: 3face2321e4104ab57f39c779d2a39e38adba0b1
https://github.com/scummvm/scummvm/commit/3face2321e4104ab57f39c779d2a39e38adba0b1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:13+01:00
Commit Message:
MM: MM1: Added drawing of monster changes
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9e2d79f4772..a078c737cb0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -312,6 +312,8 @@
defeating1: "! FOR DEFEATING THE MONSTERS !"
defeating2: "! EACH SURVIVOR RECEIVES !"
xp: "EXPERIENCE POINTS."
+ regenerate: "SOME MONSTERS REGENERATE!"
+ overcome: "SOME MONSTERS OVERCOME SPELLS!"
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 6a18bfcabb4..bbe9a1f5cd0 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -70,6 +70,10 @@ void Combat::draw() {
writeMonsters();
delaySeconds(2);
return;
+ case MONSTERS_AFFECTED:
+ writeMonsterEffects();
+ delaySeconds(3);
+ return;
default:
break;
}
@@ -339,6 +343,20 @@ void Combat::highlightNextRound() {
writeString(0, 1, s);
}
+void Combat::writeMonsterEffects() {
+ if (_monstersRegenerate)
+ writeString(0, 21, STRING["dialogs.combat.regenerate"]);
+
+ if (_monstersResistSpells) {
+ if (_textPos.y != 21)
+ _textPos.y = 20;
+
+ writeString(0, _textPos.y + 1, STRING["dialogs.combat.overcome"]);
+ }
+
+ writeMonsters();
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index aef99d9462c..7bced1fe75b 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -90,6 +90,11 @@ private:
*/
void highlightNextRound();
+ /**
+ * Write monster changes
+ */
+ void writeMonsterEffects();
+
protected:
/**
* Sets a new display mode
Commit: 19b933f93b536902c9755e0fd62b50f47ea4fa31
https://github.com/scummvm/scummvm/commit/19b933f93b536902c9755e0fd62b50f47ea4fa31
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:13+01:00
Commit Message:
MM: MM1: Started implementing monster actions
Changed paths:
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 9f66b7740c0..0ae547182f1 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -36,9 +36,16 @@ enum MonsterStatus {
MON_ASLEEP = 3, MON_MINDLESS = 4, MON_SILENCED = 5,
MON_BLINDED = 6, MON_AFRAID = 7, MON_DEAD = 8
};
+enum MonsterStatusFlag {
+ MONFLAG_AFRAID = 1, MONFLAG_BLIND = 2, MONFLAG_SILENCED = 4,
+ MONFLAG_MINDLESS = 8, MONFLAG_ASLEEP = 0x10,
+ MONFLAG_HELD = 0x20, MONFLAG_WEBBED = 0x40,
+ MONFLAG_PARALYZED = 0x80
+};
enum Field1E {
- FIELD1E_40 = 0x40
+ FIELD1E_10 = 0x10, FIELD1E_20 = 0x20,
+ FIELD1E_40 = 0x40, FIELD1E_80 = 0x80
};
struct Monster {
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 717bae03509..39ab118dbc7 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -251,7 +251,30 @@ void Combat::defeatedMonsters() {
}
void Combat::loop1() {
- // TODO
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ _monsterP = &_monsterList[i];
+ monsterIndexOf();
+
+ if (_monsterP->_field15 && _monsterP->_field15 >= _handicap3
+ && !_arr4[i]) {
+ _arr4[i] = true;
+
+ if (_monsterStatus[i] & (MONFLAG_ASLEEP | MONFLAG_HELD |
+ MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
+ checkMonsterFlees();
+ return;
+ }
+ }
+ }
+
+ if (_handicap2 == 1 && _handicap3 == 1) {
+ nextRound();
+ } else {
+ if (_handicap2 != 1)
+ --_handicap2;
+ if (_handicap3 != 1)
+ --_handicap3;
+ }
}
void Combat::proc1() {
@@ -389,8 +412,8 @@ bool Combat::moveMonsters() {
for (uint i = 0; i < _monsterList.size(); ++i) {
_advanceIndex = i;
- if (!(_monsterStatus[i] & ~MON_MINDLESS) &&
- _monsterList[i]._field1e & 0x80) {
+ if (!(_monsterStatus[i] & ~MONFLAG_SILENCED) &&
+ _monsterList[i]._field1e & FIELD1E_80) {
monsterAdvances();
hasAdvance = true;
}
@@ -479,6 +502,42 @@ void Combat::proc2() {
_val9 = (val != 100 && val <= threshold) ? 1 : 0;
}
+void Combat::checkMonsterFlees() {
+ const Encounter &enc = g_globals->_encounters;
+ byte bitset = _monsterP->_field1e;
+ int threshold = -1;
+
+ if (!(bitset & (FIELD1E_10 | FIELD1E_20))) {
+ if (enc._highestLevel < 4) {
+ } else if (enc._highestLevel < 9) {
+ threshold = 50;
+ } else if (enc._highestLevel < 14) {
+ threshold = 75;
+ } else {
+ threshold = 0;
+ }
+ } else if (!(bitset & FIELD1E_10)) {
+ if (enc._highestLevel < 9) {
+ } else if (enc._highestLevel < 14) {
+ threshold = 50;
+ } else {
+ threshold = 75;
+ }
+ } else if (!(bitset & FIELD1E_20)) {
+ if (enc._highestLevel < 14) {
+ } else {
+ threshold = 50;
+ }
+ }
+
+ if (getRandomNumber(100) >= threshold) {
+ // TODO: More
+ setMode(RUNS_AWAY);
+ } else {
+
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 1731d8cff27..ad5dd0862d4 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -66,7 +66,8 @@ protected:
Handicap _handicap = HANDICAP_EVEN;
enum Mode {
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
- NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
+ NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
+ RUNS_AWAY
};
Mode _mode = SELECT_OPTION;
@@ -156,6 +157,11 @@ protected:
*/
void updateHighestLevel();
+ /**
+ * Calculate a monster action
+ */
+ void checkMonsterFlees();
+
void defeatedMonsters();
void selectParty();
void loop1();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index bbe9a1f5cd0..a36a2e6c297 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -74,6 +74,10 @@ void Combat::draw() {
writeMonsterEffects();
delaySeconds(3);
return;
+ case RUNS_AWAY:
+ writeMonsterAction();
+ break;
+
default:
break;
}
@@ -357,6 +361,14 @@ void Combat::writeMonsterEffects() {
writeMonsters();
}
+void Combat::writeMonsterAction() {
+ writeChar(12, _monsterIndex, 0xC1);
+ resetBottom();
+ writeString(0, 20, _monsterList[_monsterIndex]._name);
+
+
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 7bced1fe75b..0b323338ce1 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -95,6 +95,11 @@ private:
*/
void writeMonsterEffects();
+ /**
+ * Handles a monster action
+ */
+ void writeMonsterAction();
+
protected:
/**
* Sets a new display mode
Commit: 8dd3e3d84c170584db058d1f1ca5b1901770b943
https://github.com/scummvm/scummvm/commit/8dd3e3d84c170584db058d1f1ca5b1901770b943
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: More implementation of monster fleeing
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index a078c737cb0..b3eb418080b 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -314,6 +314,7 @@
xp: "EXPERIENCE POINTS."
regenerate: "SOME MONSTERS REGENERATE!"
overcome: "SOME MONSTERS OVERCOME SPELLS!"
+ monster_flees: "RUNS AWAY..."
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 0ae547182f1..7f15100f941 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -40,7 +40,7 @@ enum MonsterStatusFlag {
MONFLAG_AFRAID = 1, MONFLAG_BLIND = 2, MONFLAG_SILENCED = 4,
MONFLAG_MINDLESS = 8, MONFLAG_ASLEEP = 0x10,
MONFLAG_HELD = 0x20, MONFLAG_WEBBED = 0x40,
- MONFLAG_PARALYZED = 0x80
+ MONFLAG_PARALYZED = 0x80, MONFLAG_DEAD = 0xff
};
enum Field1E {
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 39ab118dbc7..f25818c8fd4 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -425,7 +425,7 @@ bool Combat::moveMonsters() {
void Combat::monsterAdvances() {
// TODO: Shouldn't placement changes affect the arrays
_monsterList.remove_at(_advanceIndex);
- _advancingMonster = _monsterList[_advanceIndex]._name;
+ _monsterName = _monsterList[_advanceIndex]._name;
}
bool Combat::monsterChanges() {
@@ -506,6 +506,8 @@ void Combat::checkMonsterFlees() {
const Encounter &enc = g_globals->_encounters;
byte bitset = _monsterP->_field1e;
int threshold = -1;
+ _monsterName = _monsterP->_name;
+ monsterIndexOf();
if (!(bitset & (FIELD1E_10 | FIELD1E_20))) {
if (enc._highestLevel < 4) {
@@ -531,11 +533,38 @@ void Combat::checkMonsterFlees() {
}
if (getRandomNumber(100) >= threshold) {
- // TODO: More
- setMode(RUNS_AWAY);
- } else {
+ _monsterP->_experience = 0;
+ _monsterP->_field18 = 0;
+ _arr1[_monsterIndex] = 0;
+ _monsterStatus[_monsterIndex] = MONFLAG_DEAD;
+ removeMonster();
+ setMode(MONSTER_FLEES);
+ }
+ checkMonsterActions();
+}
+
+void Combat::checkMonsterActions() {
+ if (_monsterList.empty()) {
+ // TODO
}
+
+ // TODO
+}
+
+void Combat::removeMonster() {
+ bool changed;
+ do {
+ changed = false;
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ _monsterP = &_monsterList[i];
+ if (_monsterStatus[i] == MONFLAG_DEAD) {
+ _monsterList.remove_at(i);
+ changed = true;
+ break;
+ }
+ }
+ } while (changed);
}
} // namespace Game
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index ad5dd0862d4..bb3af61837e 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -56,7 +56,7 @@ protected:
int _handicap3, _handicap4;
int _attackerVal;
int _totalExperience;
- Common::String _advancingMonster;
+ Common::String _monsterName;
bool _monstersResistSpells;
bool _monstersRegenerate;
enum Handicap {
@@ -67,7 +67,7 @@ protected:
enum Mode {
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
- RUNS_AWAY
+ MONSTER_FLEES
};
Mode _mode = SELECT_OPTION;
@@ -162,6 +162,11 @@ protected:
*/
void checkMonsterFlees();
+ /**
+ * Check other monster actions
+ */
+ void checkMonsterActions();
+
void defeatedMonsters();
void selectParty();
void loop1();
@@ -171,6 +176,7 @@ protected:
void monsterAdvances();
bool monsterChanges();
void proc2();
+ void removeMonster();
};
} // namespace Game
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index a36a2e6c297..09f631e7c44 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -63,7 +63,7 @@ void Combat::draw() {
delaySeconds(1);
return;
case MONSTER_ADVANCES:
- writeString(0, 20, _advancingMonster);
+ writeString(0, 20, _monsterName);
writeString(STRING["dialogs.combat.advances"]);
writeSpaces(30);
writeRound();
@@ -74,9 +74,10 @@ void Combat::draw() {
writeMonsterEffects();
delaySeconds(3);
return;
- case RUNS_AWAY:
+ case MONSTER_FLEES:
writeMonsterAction();
- break;
+ delaySeconds(3);
+ return;
default:
break;
@@ -111,13 +112,16 @@ void Combat::timeout() {
switch (_mode) {
case NEXT_ROUND:
nextRound2();
- break;
+ return;
case MONSTER_ADVANCES:
nextRound3();
- break;
+ return;
case MONSTERS_AFFECTED:
combatLoop();
- break;
+ return;
+ case MONSTER_FLEES:
+ checkMonsterActions();
+ return;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_spells;
spells._s.bless = 0;
@@ -133,7 +137,7 @@ void Combat::timeout() {
break;
}
- redraw();
+// redraw();
}
bool Combat::msgKeypress(const KeypressMessage &msg) {
@@ -283,7 +287,7 @@ void Combat::writeMonsterStatus(int monsterNum) {
writeDots();
int status;
- if (statusBits == 0xff) {
+ if (statusBits == MONFLAG_DEAD) {
status = MON_DEAD;
} else {
for (status = MON_PARALYZED; !(statusBits & 0x80);
@@ -364,9 +368,8 @@ void Combat::writeMonsterEffects() {
void Combat::writeMonsterAction() {
writeChar(12, _monsterIndex, 0xC1);
resetBottom();
- writeString(0, 20, _monsterList[_monsterIndex]._name);
-
-
+ writeString(0, 20, _monsterName);
+ writeString(STRING["dialogs.combat.monster_flees"]);
}
} // namespace Views
Commit: bdd433d74554f510eca35da98d7e21c9cdff18c9
https://github.com/scummvm/scummvm/commit/bdd433d74554f510eca35da98d7e21c9cdff18c9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: Change _monsterIndex to _monsterCount
Changed paths:
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 8a96bb464ed..6c3bb4aa316 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -38,7 +38,8 @@ void Encounter::execute() {
_alignmentsChanged = 0;
if (!_flag) {
- _levelIndex = _monsterIndex = 0;
+ _monsterList.clear();
+ _levelIndex = 0;
}
_totalLevels = _highestLevel = 0;
@@ -75,32 +76,32 @@ void Encounter::execute() {
comp = MIN(maxVal, 10);
}
- assert(_monsterIndex < MAX_COMBAT_MONSTERS);
- _arr1[_monsterIndex] = comp;
+ assert(_monsterCount < MAX_COMBAT_MONSTERS);
+ _arr1[_monsterCount] = comp;
_monsterNum16 = comp;
_levelIndex += comp;
_monsterNum = getRandomNumber(16);
- _monsIndexes[_monsterIndex] = _monsterNum;
- _monsterIndex = (_monsterIndex + 1) & 0xff;
+ _monsIndexes[_monsterCount] = _monsterNum;
+ _monsterCount = (_monsterCount + 1) & 0xff;
- if (_monsterIndex < MAX_COMBAT_MONSTERS) {
- if (_monsterIndex >= map[Maps::MAP_MAX_MONSTERS])
+ if (_monsterCount < MAX_COMBAT_MONSTERS) {
+ if (_monsterCount >= map[Maps::MAP_MAX_MONSTERS])
goto exit_loop;
monsterP = getMonster();
maxVal = getRandomNumber(monsterP->_count);
for (int i = 0; i < maxVal; ++i) {
- assert(_monsterIndex > 0);
- _arr1[_monsterIndex] = _arr1[_monsterIndex - 1];
- _levelIndex += _arr1[_monsterIndex];
- _monsIndexes[_monsterIndex] = _monsIndexes[_monsterIndex - 1];
+ assert(_monsterCount > 0);
+ _arr1[_monsterCount] = _arr1[_monsterCount - 1];
+ _levelIndex += _arr1[_monsterCount];
+ _monsIndexes[_monsterCount] = _monsIndexes[_monsterCount - 1];
- if (++_monsterIndex >= MAX_COMBAT_MONSTERS)
+ if (++_monsterCount >= MAX_COMBAT_MONSTERS)
goto exit_loop;
- if (_monsterIndex >= map[Maps::MAP_MAX_MONSTERS])
+ if (_monsterCount >= map[Maps::MAP_MAX_MONSTERS])
goto exit_loop;
}
} else {
@@ -111,7 +112,7 @@ void Encounter::execute() {
exit_loop:
_monsterList.clear();
- for (int i = 0; i < _monsterIndex; ++i) {
+ for (int i = 0; i < _monsterCount; ++i) {
maxVal = (_arr1[i] - 1) * 16 + _monsIndexes[i];
if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
_arr1[i] = 10;
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 734ca374809..d3c6aa5bbc9 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -55,7 +55,7 @@ public:
int _bribeAlignmentCtr = 0, _bribeFleeCtr = 0;
int _alignmentsChanged = 0;
int _monsterImgNum = 0;
- int _monsterIndex = 0; // == _monsterList.size()
+ int _monsterCount = 0; // == _monsterList.size()
int _highestLevel = 0;
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
Commit: 654778837a1d6aff2c610b98464057e2ab361eba
https://github.com/scummvm/scummvm/commit/654778837a1d6aff2c610b98464057e2ab361eba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: Further implementing combat
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index ec0e17c9221..4ba61fe48b5 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -143,6 +143,13 @@ void Events::popView() {
}
}
+void Events::clearViews() {
+ if (!_views.empty())
+ focusedView()->msgUnfocus(UnfocusMessage());
+
+ _views.clear();
+}
+
/*------------------------------------------------------------------------*/
Bounds::Bounds(Common::Rect &innerBounds) :
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 2279746f32a..cb76835436c 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -281,6 +281,11 @@ public:
void addView(UIElement *ui);
void addView(const Common::String &name);
+ /**
+ * Clears the view list
+ */
+ void clearViews();
+
/**
* Pops a view from the view stack
*/
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index f25818c8fd4..48035df05e8 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -42,7 +42,7 @@ void Combat::clear() {
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_val6 = _val7 = 0;
- _val8 = _val9 = 0;
+ _val8 = _val9 = _val10 = 0;
_advanceIndex = 0;
_handicap1 = _handicap2 = 0;
_handicap3 = _handicap4 = 0;
@@ -539,16 +539,39 @@ void Combat::checkMonsterFlees() {
_monsterStatus[_monsterIndex] = MONFLAG_DEAD;
removeMonster();
setMode(MONSTER_FLEES);
+ } else {
+ checkMonsterSpells();
}
-
- checkMonsterActions();
}
-void Combat::checkMonsterActions() {
+void Combat::checkMonsterSpells() {
if (_monsterList.empty()) {
- // TODO
+ setMode(DEFEATED_MONSTERS);
+ return;
}
+ if (_monsterStatus[_monsterIndex] & MONFLAG_MINDLESS) {
+ setMode(MONSTER_WANDERS);
+ } else {
+ if (!_monsterP->_field1c || (_monsterP->_field1c & 0x80) ||
+ (getRandomNumber(100) >= _monsterP->_field1d) ||
+ !(_monsterP->_field1e & 0xf))
+ checkMonsterActions();
+ else {
+ _monsterP->_field1e--;
+ if (!_monsterP->_field1c || _monsterP->_field1c >= 33) {
+ checkMonsterActions();
+ } else {
+ // TODO: Monsters spell casting?
+ }
+ }
+ }
+}
+
+void Combat::checkMonsterActions() {
+
+
+
// TODO
}
@@ -567,6 +590,24 @@ void Combat::removeMonster() {
} while (changed);
}
+void Combat::checkParty() {
+ _val10 = 0;
+
+ bool partyAlive = false;
+ for (auto &c : g_globals->_party) {
+ if (!(c._condition & (DEAD | BAD_CONDITION)))
+ partyAlive = true;
+ }
+
+ if (!partyAlive) {
+ g_events->clearViews();
+ g_events->replaceView("Dead");
+ return;
+ }
+
+
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index bb3af61837e..80fb37651a1 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -50,7 +50,7 @@ protected:
int _monsterIndex, _currentChar;
char _val2, _val3, _val4, _val5;
byte _val6, _val7;
- int _val8, _val9;
+ int _val8, _val9, _val10;
int _advanceIndex;
int _handicap1, _handicap2;
int _handicap3, _handicap4;
@@ -67,7 +67,7 @@ protected:
enum Mode {
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
- MONSTER_FLEES
+ MONSTER_FLEES, MONSTER_WANDERS
};
Mode _mode = SELECT_OPTION;
@@ -162,6 +162,11 @@ protected:
*/
void checkMonsterFlees();
+ /**
+ * Check if monster is mindless and wandering
+ */
+ void checkMonsterSpells();
+
/**
* Check other monster actions
*/
@@ -177,6 +182,7 @@ protected:
bool monsterChanges();
void proc2();
void removeMonster();
+ void checkParty();
};
} // namespace Game
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 09f631e7c44..344cd877469 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -75,10 +75,10 @@ void Combat::draw() {
delaySeconds(3);
return;
case MONSTER_FLEES:
+ case MONSTER_WANDERS:
writeMonsterAction();
delaySeconds(3);
return;
-
default:
break;
}
@@ -120,7 +120,12 @@ void Combat::timeout() {
combatLoop();
return;
case MONSTER_FLEES:
- checkMonsterActions();
+ checkMonsterSpells();
+ return;
+ case MONSTER_WANDERS:
+ writeParty();
+ writeMonsters();
+ checkParty();
return;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_spells;
Commit: b93fc023778a317df02bdfa643158fafea529ec3
https://github.com/scummvm/scummvm/commit/b93fc023778a317df02bdfa643158fafea529ec3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: Beginnings of monster spell casting handler
Changed paths:
A engines/mm/mm1/game/spells_monsters.cpp
A engines/mm/mm1/game/spells_monsters.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/maps/maps.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b3eb418080b..92a6256c313 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -729,6 +729,11 @@ spells:
enter_to_cast: "'ENTER' TO CAST"
cast_on: "CAST ON: '1'-'%d'?"
which_town: "WHICH TOWN (1-5)?"
+monster_spells:
+ casts: "CASTS "
+ fails_to_cast: "FAILS TO CAST A SPELL"
+ a_curse: "A CURSE"
+
maps:
map00:
sign: "A SIGN ABOVE THE DOOR READS: "
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 48035df05e8..88b8069de67 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -191,6 +191,10 @@ void Combat::setupHandicap() {
_handicap4 = 0;
}
+bool Combat::canMonsterCast() const {
+ return !(g_maps->_currentState & Maps::SFLAG_DISABLE_MONSTER_SPELLS) &&
+ !(_monsterStatus[_monsterIndex] & (MONFLAG_BLIND | MONFLAG_SILENCED));
+}
void Combat::combatLoop() {
if (_monsterIndex != 0) {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 80fb37651a1..867a00ca8f4 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -27,12 +27,13 @@
#include "mm/mm1/data/party.h"
#include "mm/mm1/game/game_logic.h"
#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/game/spells_monsters.h"
namespace MM {
namespace MM1 {
namespace Game {
-class Combat : public GameLogic {
+class Combat : public GameLogic, public SpellsMonsters {
protected:
Common::Array<Monster> &_monsterList;
int _monstersCount = 0;
@@ -124,6 +125,10 @@ protected:
*/
void setupHandicap();
+ /*------- Inherited virtual methods ------*/
+
+ bool canMonsterCast() const override;
+
/*------- combat execution ------*/
/**
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
new file mode 100644
index 00000000000..86e3629fd8b
--- /dev/null
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -0,0 +1,153 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/game/spells_monsters.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
+ &SpellsMonsters::spell01_curse,
+ &SpellsMonsters::spell02_energyBlast,
+ &SpellsMonsters::spell03_fire,
+ &SpellsMonsters::spell04_blindness,
+ &SpellsMonsters::spell05_sprayPoison,
+ &SpellsMonsters::spell06_sprayAcid,
+ &SpellsMonsters::spell07_sleep,
+ &SpellsMonsters::spell08_paralyze,
+ &SpellsMonsters::spell09_dispell,
+ &SpellsMonsters::spell10_lightningBolt,
+ &SpellsMonsters::spell11_strangeGas,
+ &SpellsMonsters::spell12_explode,
+ &SpellsMonsters::spell13_fireball,
+ &SpellsMonsters::spell14_fire2,
+ &SpellsMonsters::spell15_gazes,
+ &SpellsMonsters::spell16_acidArrow,
+ &SpellsMonsters::spell17_elements,
+ &SpellsMonsters::spell18_coldBeam,
+ &SpellsMonsters::spell19_dancingSword,
+ &SpellsMonsters::spell20_magicDrain,
+ &SpellsMonsters::spell21_fingerOfDeath,
+ &SpellsMonsters::spell22_sunRay,
+ &SpellsMonsters::spell23_disintegration,
+ &SpellsMonsters::spell24_commandsEnergy,
+ &SpellsMonsters::spell25_poison,
+ &SpellsMonsters::spell26_lightning,
+ &SpellsMonsters::spell27_frost,
+ &SpellsMonsters::spell28_spikes,
+ &SpellsMonsters::spell29_acid,
+ &SpellsMonsters::spell30_fire,
+ &SpellsMonsters::spell31_energy,
+ &SpellsMonsters::spell32_swarm
+};
+
+void SpellsMonsters::castMonsterSpell(int spellNum) {
+ _mmVal1 = _mmVal2 = _mmVal3 = _mmVal4 = 0;
+ _monsterSpellMessage = "";
+ (this->*SPELLS[spellNum - 1])();
+}
+
+void SpellsMonsters::spell01_curse() {
+ if (casts())
+ g_globals->_spells._s.cursed = MIN(255,
+ (int)g_globals->_spells._s.cursed + 1);
+
+ _monsterSpellMessage += STRING["monster_spells.a_curse"];
+}
+
+void SpellsMonsters::spell02_energyBlast() {}
+
+void SpellsMonsters::spell03_fire() {}
+
+void SpellsMonsters::spell04_blindness() {}
+
+void SpellsMonsters::spell05_sprayPoison() {}
+
+void SpellsMonsters::spell06_sprayAcid() {}
+
+void SpellsMonsters::spell07_sleep() {}
+
+void SpellsMonsters::spell08_paralyze() {}
+
+void SpellsMonsters::spell09_dispell() {}
+
+void SpellsMonsters::spell10_lightningBolt() {}
+
+void SpellsMonsters::spell11_strangeGas() {}
+
+void SpellsMonsters::spell12_explode() {}
+
+void SpellsMonsters::spell13_fireball() {}
+
+void SpellsMonsters::spell14_fire2() {}
+
+void SpellsMonsters::spell15_gazes() {}
+
+void SpellsMonsters::spell16_acidArrow() {}
+
+void SpellsMonsters::spell17_elements() {}
+
+void SpellsMonsters::spell18_coldBeam() {}
+
+void SpellsMonsters::spell19_dancingSword() {}
+
+void SpellsMonsters::spell20_magicDrain() {}
+
+void SpellsMonsters::spell21_fingerOfDeath() {}
+
+void SpellsMonsters::spell22_sunRay() {}
+
+void SpellsMonsters::spell23_disintegration() {}
+
+void SpellsMonsters::spell24_commandsEnergy() {}
+
+void SpellsMonsters::spell25_poison() {}
+
+void SpellsMonsters::spell26_lightning() {}
+
+void SpellsMonsters::spell27_frost() {}
+
+void SpellsMonsters::spell28_spikes() {}
+
+void SpellsMonsters::spell29_acid() {}
+
+void SpellsMonsters::spell30_fire() {}
+
+void SpellsMonsters::spell31_energy() {}
+
+void SpellsMonsters::spell32_swarm() {}
+
+bool SpellsMonsters::casts() {
+ if (canMonsterCast()) {
+ _monsterSpellMessage += STRING["monster_spells.casts"];
+ return true;
+ } else {
+ _monsterSpellMessage += STRING["monster_spells.fails_to_cast"];
+ return false;
+ }
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
new file mode 100644
index 00000000000..dfe68ecc3ef
--- /dev/null
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_SPELLS_MONSTERS
+#define MM1_GAME_SPELLS_MONSTERS
+
+#include "common/str.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+#define MONSTER_SPELLS_COUNT 32
+
+class SpellsMonsters;
+typedef void (SpellsMonsters::*SpellMonstersSpell)();
+
+class SpellsMonsters {
+private:
+ static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
+ Common::String _monsterSpellMessage;
+ int _mmVal1 = 0, _mmVal2 = 0;
+ int _mmVal3 = 0, _mmVal4 = 0;
+
+ void spell01_curse();
+ void spell02_energyBlast();
+ void spell03_fire();
+ void spell04_blindness();
+ void spell05_sprayPoison();
+ void spell06_sprayAcid();
+ void spell07_sleep();
+ void spell08_paralyze();
+ void spell09_dispell();
+ void spell10_lightningBolt();
+ void spell11_strangeGas();
+ void spell12_explode();
+ void spell13_fireball();
+ void spell14_fire2();
+ void spell15_gazes();
+ void spell16_acidArrow();
+ void spell17_elements();
+ void spell18_coldBeam();
+ void spell19_dancingSword();
+ void spell20_magicDrain();
+ void spell21_fingerOfDeath();
+ void spell22_sunRay();
+ void spell23_disintegration();
+ void spell24_commandsEnergy();
+ void spell25_poison();
+ void spell26_lightning();
+ void spell27_frost();
+ void spell28_spikes();
+ void spell29_acid();
+ void spell30_fire();
+ void spell31_energy();
+ void spell32_swarm();
+
+ bool casts();
+
+protected:
+ virtual bool canMonsterCast() const = 0;
+
+public:
+ /**
+ * Monster casts a spell
+ */
+ void castMonsterSpell(int spellNum);
+
+ /**
+ * Gets a spell message
+ */
+ Common::String getMonsterSpellMessage() const {
+ return _monsterSpellMessage;
+ }
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index ec11d13390d..ebc3a84de35 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -41,6 +41,10 @@ enum DirMask {
DIRMASK_S = 0xC, DIRMASK_W = 3
};
+enum StateFlag {
+ SFLAG_DISABLE_MONSTER_SPELLS = 2
+};
+
/**
* Container for all the game maps
*/
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b8b80e91b35..3e0cde86076 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -28,6 +28,7 @@ MODULE_OBJS := \
mm1/game/rest.o \
mm1/game/search.o \
mm1/game/spell_casting.o \
+ mm1/game/spells_monsters.o \
mm1/game/view_base.o \
mm1/gfx/dta.o \
mm1/gfx/gfx.o \
Commit: ca2630c83631e2ebf72893830d873ebb227bb8d2
https://github.com/scummvm/scummvm/commit/ca2630c83631e2ebf72893830d873ebb227bb8d2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: Starting monster spells support methods
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 92a6256c313..231a068a2fb 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -733,6 +733,36 @@ monster_spells:
casts: "CASTS "
fails_to_cast: "FAILS TO CAST A SPELL"
a_curse: "A CURSE"
+ energy_blast: "ENERGY BLAST"
+ blindles: "BLINDNESS"
+ sprays_poison: "SPRAYS POISON"
+ sprays_acid: "SPRAYS ACID"
+ sleep: "SLEEP"
+ paralyze: "PARALYZE"
+ dispel: "DISPEL"
+ lightningBolt: "LIGHTNING BOLT"
+ strangeGas: "STRANGE GAS"
+ explode: "EXPLODE"
+ fireball: "FIREBALL"
+ gazes: "GAZES"
+ acidArrow: "ACID ARROW"
+ calls_elements: "CALLS UPPON THE ELEMENTS"
+ coldBeam: "COLD BEAM"
+ dancingSword: "DANCING SWORD"
+ magicDrain: "MAGIC DRAIN"
+ fingerOfDeath: "FINGER OF DEATH"
+ sunRay: "SUN RAY"
+ disintegration: "DISINTEGRATION"
+ commandsEnergy: "COMMANDS ENERGY"
+ poison: "POISON"
+ lightning: "LIGHTNING"
+ frost: "FROST"
+ spikes: "SPIKES"
+ acid: "ACID"
+ fire: "FIRE"
+ energy: "ENERGY"
+ swarm: "SWARM"
+ breathes: "BREATHES "
maps:
map00:
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 867a00ca8f4..e9b00332ae1 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -33,7 +33,7 @@ namespace MM {
namespace MM1 {
namespace Game {
-class Combat : public GameLogic, public SpellsMonsters {
+class Combat : public SpellsMonsters {
protected:
Common::Array<Monster> &_monsterList;
int _monstersCount = 0;
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 86e3629fd8b..344a8d22139 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -69,14 +69,21 @@ void SpellsMonsters::castMonsterSpell(int spellNum) {
}
void SpellsMonsters::spell01_curse() {
- if (casts())
+ if (casts()) {
+ _monsterSpellMessage += STRING["monster_spells.a_curse"];
g_globals->_spells._s.cursed = MIN(255,
(int)g_globals->_spells._s.cursed + 1);
-
- _monsterSpellMessage += STRING["monster_spells.a_curse"];
+ }
}
-void SpellsMonsters::spell02_energyBlast() {}
+void SpellsMonsters::spell02_energyBlast() {
+ if (casts()) {
+ _monsterSpellMessage += STRING["monster_spells.energy_blast"];
+ ++_mmVal1;
+ _mmVal4 = getRandomNumber(16) + 4;
+ proc1();
+ }
+}
void SpellsMonsters::spell03_fire() {}
@@ -148,6 +155,64 @@ bool SpellsMonsters::casts() {
}
}
+void SpellsMonsters::proc1() {
+ chooseCharacter();
+ proc3();
+}
+
+void SpellsMonsters::chooseCharacter() {
+ _monsterSpellMessage += ':';
+
+ // Choose a random character
+ g_globals->_currCharacter = &g_globals->_party[
+ getRandomNumber(g_globals->_party.size()) - 1
+ ];
+
+ if (g_globals->_currCharacter->_condition & (BAD_CONDITION | UNCONSCIOUS)) {
+ // Can't use character, so sequently scan party
+ // to find a character that can be used
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ if (g_globals->_currCharacter->_condition & (BAD_CONDITION | UNCONSCIOUS))
+ break;
+ }
+ }
+}
+
+void SpellsMonsters::proc3() {
+ _mmVal5 = 1;
+ _mmVal6 = _mmVal4;
+ proc4();
+ proc5();
+ proc6();
+
+ if (g_globals->_spells._s.power_shield)
+ _mmVal6 = 1;
+
+ proc7();
+ proc8();
+}
+
+void SpellsMonsters::proc4() {
+
+}
+
+void SpellsMonsters::proc5() {
+
+}
+
+void SpellsMonsters::proc6() {
+
+}
+
+void SpellsMonsters::proc7() {
+
+}
+
+void SpellsMonsters::proc8() {
+
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index dfe68ecc3ef..5e9cd7674f9 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -22,6 +22,7 @@
#ifndef MM1_GAME_SPELLS_MONSTERS
#define MM1_GAME_SPELLS_MONSTERS
+#include "mm/mm1/game/game_logic.h"
#include "common/str.h"
namespace MM {
@@ -33,12 +34,13 @@ namespace Game {
class SpellsMonsters;
typedef void (SpellsMonsters::*SpellMonstersSpell)();
-class SpellsMonsters {
+class SpellsMonsters : public GameLogic {
private:
static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
Common::String _monsterSpellMessage;
int _mmVal1 = 0, _mmVal2 = 0;
int _mmVal3 = 0, _mmVal4 = 0;
+ int _mmVal5 = 0, _mmVal6 = 0;
void spell01_curse();
void spell02_energyBlast();
@@ -74,6 +76,14 @@ private:
void spell32_swarm();
bool casts();
+ void proc1();
+ void chooseCharacter();
+ void proc3();
+ void proc4();
+ void proc5();
+ void proc6();
+ void proc7();
+ void proc8();
protected:
virtual bool canMonsterCast() const = 0;
Commit: ad3fc28e6fbdda0bf9f7b3187654cbe0727e70fd
https://github.com/scummvm/scummvm/commit/ad3fc28e6fbdda0bf9f7b3187654cbe0727e70fd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: Further monster spell support methods
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/messages.h
engines/mm/mm1/sound.h
engines/mm/mm1/views/game_messages.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 231a068a2fb..e9b6403668d 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -732,6 +732,13 @@ spells:
monster_spells:
casts: "CASTS "
fails_to_cast: "FAILS TO CAST A SPELL"
+ not_affected: "IS NOT AFFECTED!"
+ takes: "TAKES "
+ point: "POINT"
+ points: "POINTS"
+ of_damage: "OF DAMAGE!"
+ goes_down: "GOES DOWN!!!"
+ dies: "DIES!"
a_curse: "A CURSE"
energy_blast: "ENERGY BLAST"
blindles: "BLINDNESS"
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 344a8d22139..127d67fb24f 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -22,6 +22,7 @@
#include "mm/mm1/game/spells_monsters.h"
#include "mm/mm1/maps/maps.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -62,15 +63,19 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
&SpellsMonsters::spell32_swarm
};
-void SpellsMonsters::castMonsterSpell(int spellNum) {
+void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
_mmVal1 = _mmVal2 = _mmVal3 = _mmVal4 = 0;
- _monsterSpellMessage = "";
+
+ // All spell messages start with the monster who casts it
+ _lines.clear();
+ _lines.push_back(Line(monsterName));
+
(this->*SPELLS[spellNum - 1])();
}
void SpellsMonsters::spell01_curse() {
if (casts()) {
- _monsterSpellMessage += STRING["monster_spells.a_curse"];
+ add(STRING["monster_spells.a_curse"]);
g_globals->_spells._s.cursed = MIN(255,
(int)g_globals->_spells._s.cursed + 1);
}
@@ -78,7 +83,7 @@ void SpellsMonsters::spell01_curse() {
void SpellsMonsters::spell02_energyBlast() {
if (casts()) {
- _monsterSpellMessage += STRING["monster_spells.energy_blast"];
+ add(STRING["monster_spells.energy_blast"]);
++_mmVal1;
_mmVal4 = getRandomNumber(16) + 4;
proc1();
@@ -147,21 +152,21 @@ void SpellsMonsters::spell32_swarm() {}
bool SpellsMonsters::casts() {
if (canMonsterCast()) {
- _monsterSpellMessage += STRING["monster_spells.casts"];
+ add(STRING["monster_spells.casts"]);
return true;
} else {
- _monsterSpellMessage += STRING["monster_spells.fails_to_cast"];
+ add(STRING["monster_spells.fails_to_cast"]);
return false;
}
}
void SpellsMonsters::proc1() {
chooseCharacter();
- proc3();
+ handleDamage();
}
void SpellsMonsters::chooseCharacter() {
- _monsterSpellMessage += ':';
+ add(':');
// Choose a random character
g_globals->_currCharacter = &g_globals->_party[
@@ -179,38 +184,111 @@ void SpellsMonsters::chooseCharacter() {
}
}
-void SpellsMonsters::proc3() {
+bool SpellsMonsters::isCharAffected() const {
+ int val = g_globals->_currCharacter->_arr58._s._v58 +
+ g_globals->_spells._s.magic;
+ return randomThreshold(val);
+}
+
+void SpellsMonsters::handleDamage() {
_mmVal5 = 1;
- _mmVal6 = _mmVal4;
- proc4();
- proc5();
- proc6();
+ _damage = _mmVal4;
+
+ if (charAffected()) {
+ if (isEffective()) {
+ proc6();
- if (g_globals->_spells._s.power_shield)
- _mmVal6 = 1;
+ if (g_globals->_spells._s.power_shield)
+ _damage = 1;
- proc7();
- proc8();
+ writeDamage();
+ subtractDamage();
+ }
+ }
}
-void SpellsMonsters::proc4() {
+bool SpellsMonsters::charAffected() {
+ _lines.push_back(Line(0, 2, Common::String::format("%s ",
+ g_globals->_currCharacter->_name)));
+
+ if (_mmVal1 && !isCharAffected()) {
+ _lines.back()._text += STRING["monster_spells.not_affected"];
+ return false;
+ }
+ return true;
}
-void SpellsMonsters::proc5() {
+bool SpellsMonsters::isEffective() {
+ if (_mmVal2) {
+ proc9();
+
+ if (_mmVal7) {
+ if (_mmVal5) {
+ _damage >>= 1;
+ } else {
+ _lines.back()._text += STRING["monster_spells.not_affected"];
+ return false;
+ }
+ }
+ }
+ return true;
}
void SpellsMonsters::proc6() {
}
-void SpellsMonsters::proc7() {
+void SpellsMonsters::writeDamage() {
+ add(STRING["monster_spells.takes"]);
+ add(Common::String::format("%d ", _damage));
+ add(STRING[_damage > 1 ? "monster_spells.points" : "monster_spells.point"]);
+ add(' ');
+
+ if (_lines.back()._text.size() >= 30)
+ add('!');
+ else
+ add(STRING["monster_spells.of_damage"]);
+}
+
+void SpellsMonsters::subtractDamage() {
+ Character &c = *g_globals->_currCharacter;
+ int newHp = c._hpBase - _damage;
+ if (newHp > 0) {
+ c._hpBase = newHp;
+
+ } else {
+ c._hpBase = 0;
+
+ if (!(c._condition & (BAD_CONDITION | UNCONSCIOUS))) {
+ c._condition |= UNCONSCIOUS;
+ add(c._name);
+ add(' ');
+ add(STRING["monster_spells.goes_down"]);
+ Sound::sound2(SOUND_8);
+
+ } else {
+ if (c._condition & BAD_CONDITION)
+ c._condition = BAD_CONDITION | DEAD;
+
+ _lines.push_back(Line(0, _lines.back().y + 1,
+ Common::String::format("%s %s",
+ c._name, STRING["monster_spells.dies"].c_str())));
+ Sound::sound2(SOUND_8);
+ }
+ }
}
-void SpellsMonsters::proc8() {
+void SpellsMonsters::proc9() {
+ const Character &c = *g_globals->_currCharacter;
+ int val = c._level._current * 4 + c._luck._current;
+ if (c._class == PALADIN)
+ val += 20;
+ int randVal = getRandomNumber(100);
+ _mmVal7 = randVal < 99 && randVal <= val ? 1 : 0;
}
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 5e9cd7674f9..88f4c5a1728 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -23,6 +23,7 @@
#define MM1_GAME_SPELLS_MONSTERS
#include "mm/mm1/game/game_logic.h"
+#include "mm/mm1/messages.h"
#include "common/str.h"
namespace MM {
@@ -37,10 +38,11 @@ typedef void (SpellsMonsters::*SpellMonstersSpell)();
class SpellsMonsters : public GameLogic {
private:
static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
- Common::String _monsterSpellMessage;
+ LineArray _lines;
int _mmVal1 = 0, _mmVal2 = 0;
int _mmVal3 = 0, _mmVal4 = 0;
- int _mmVal5 = 0, _mmVal6 = 0;
+ int _mmVal5 = 0, _damage = 0;
+ int _mmVal7 = 0;
void spell01_curse();
void spell02_energyBlast();
@@ -75,15 +77,63 @@ private:
void spell31_energy();
void spell32_swarm();
+ /**
+ * Called to determine whether the spell can be cast
+ */
bool casts();
- void proc1();
+
+ /**
+ * Adds text to the current line
+ */
+ void add(const Common::String &msg) {
+ _lines.back()._text += msg;
+ }
+ void add(char c) {
+ _lines.back()._text += c;
+ }
+
+ /**
+ * Randomly chooses a character in the party
+ */
void chooseCharacter();
- void proc3();
- void proc4();
- void proc5();
+
+ /**
+ * Checks whether the character is affected by the spell,
+ * and if so writes out the damage and whether the
+ * character is knocked unconscious or dies
+ */
+ void handleDamage();
+
+ /**
+ * Checks if character is affected by spell,
+ * and adds to the message if not
+ */
+ bool charAffected();
+
+ /**
+ * Returns true if character is affected so spell
+ */
+ bool isCharAffected() const;
+
+ /**
+ * Checks random range
+ */
+ bool randomThreshold(int threshold) const {
+ int v = getRandomNumber(120);
+ return v < 3 || v >= threshold;
+ }
+
+ bool isEffective();
+
+ /**
+ * Writes out how much damage the character suffers
+ */
+ void writeDamage();
+
+ void proc1();
void proc6();
- void proc7();
- void proc8();
+ void subtractDamage();
+ void proc9();
protected:
virtual bool canMonsterCast() const = 0;
@@ -92,13 +142,13 @@ public:
/**
* Monster casts a spell
*/
- void castMonsterSpell(int spellNum);
+ void castMonsterSpell(const Common::String &monsterName, int spellNum);
/**
* Gets a spell message
*/
- Common::String getMonsterSpellMessage() const {
- return _monsterSpellMessage;
+ const LineArray &getMonsterSpellMessage() const {
+ return _lines;
}
};
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index bfcdbda9f5b..5b6abbd39ed 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -78,19 +78,24 @@ struct GameMessage : public Message {
_name(name) {}
};
+struct Line : public Common::Point {
+ Common::String _text;
+
+ Line() {
+ }
+ Line(const Common::String &text) :
+ Common::Point(-1, -1), _text(text) {
+ }
+ Line(int x1, int y1, const Common::String &text) :
+ Common::Point(x1, y1), _text(text) {
+ }
+};
+typedef Common::Array<Line> LineArray;
+
typedef void (*YNCallback)();
typedef void (*KeyCallback)(const Common::KeyState &keyState);
struct InfoMessage : public Message {
- struct Line : public Common::Point {
- Common::String _text;
-
- Line() {}
- Line(const Common::String &text) :
- Common::Point(-1, -1), _text(text) {}
- Line(int x1, int y1, const Common::String &text) :
- Common::Point(x1, y1), _text(text) {}
- };
- Common::Array<Line> _lines;
+ LineArray _lines;
YNCallback _ynCallback = nullptr;
KeyCallback _keyCallback = nullptr;
bool _largeMessage = false;
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
index 34e578d8846..c6b11a90abf 100644
--- a/engines/mm/mm1/sound.h
+++ b/engines/mm/mm1/sound.h
@@ -25,7 +25,7 @@
namespace MM {
namespace MM1 {
-enum SoundId { SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3 };
+enum SoundId { SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3, SOUND_8 = 8 };
class Sound {
public:
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
index cbc93db391c..7af5456a863 100644
--- a/engines/mm/mm1/views/game_messages.h
+++ b/engines/mm/mm1/views/game_messages.h
@@ -31,7 +31,7 @@ namespace Views {
class GameMessages : public TextView {
private:
- Common::Array<InfoMessage::Line> _lines;
+ Common::Array<Line> _lines;
YNCallback _ynCallback = nullptr;
KeyCallback _keyCallback = nullptr;
public:
Commit: 00de7b5e61dd4283cc9813de0eb40840a11fe1dd
https://github.com/scummvm/scummvm/commit/00de7b5e61dd4283cc9813de0eb40840a11fe1dd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: Spell monsters elemental damage types
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/create_characters.cpp
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 814643e8ec2..ce7c3abcaae 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -30,7 +30,7 @@ static const int CLASS_HP_PER_LEVEL[6] = {
12, 10, 10, 8, 6, 8
};
-Arr58::Arr58() {
+Resistances::Resistances() {
for (int i = 0; i < 8; ++i)
_arr[i].clear();
}
@@ -178,10 +178,10 @@ void Character::clear() {
_alignmentInitial = GOOD;
_alignment = GOOD;
- _arr58._s._v58.clear();
- _arr58._s._v62.clear();
- _arr58._s._v64.clear();
- _arr58._s._v66.clear();
+ _resistances._s._magic.clear();
+ _resistances._s._fear.clear();
+ _resistances._s._poison.clear();
+ _resistances._s._psychic.clear();
_v6c = _alignmentCtr = 0;
}
@@ -418,7 +418,7 @@ void Character::updateSP() {
void Character::update58() {
for (int i = 0; i < 8; ++i)
- _arr58._arr[i]._current = _arr58._arr[i]._base;
+ _resistances._arr[i]._current = _resistances._arr[i]._base;
}
Common::String Character::getConditionString() const {
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index c5e5b3b87b2..df58f62ec56 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -56,6 +56,13 @@ enum Condition {
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
};
+enum Resistance {
+ RESISTANCE_MAGIC = 0, RESISTANCE_FIRE = 1, RESISTANCE_COLD = 2,
+ RESISTANCE_ELECTRICITY = 3, RESISTANCE_ACID = 4,
+ RESISTANCE_FEAR = 5, RESISTANCE_POISON = 6,
+ RESISTANCE_PSYCHIC = 7
+};
+
class Inventory {
public:
struct Entry {
@@ -184,22 +191,22 @@ struct AttributePair16 {
}
};
-struct Arr58Fields {
- AttributePair _v58;
- AttributePair _v5a;
- AttributePair _v5c;
- AttributePair _v5e;
- AttributePair _v60;
- AttributePair _v62;
- AttributePair _v64;
- AttributePair _v66;
+struct ResistanceFields {
+ AttributePair _magic;
+ AttributePair _fire;
+ AttributePair _cold;
+ AttributePair _electricity;
+ AttributePair _acid;
+ AttributePair _fear;
+ AttributePair _poison;
+ AttributePair _psychic;
};
-union Arr58 {
- Arr58Fields _s;
+union Resistances {
+ ResistanceFields _s;
AttributePair _arr[8];
- Arr58();
+ Resistances();
};
struct Character {
@@ -232,9 +239,9 @@ struct Character {
uint8 _condition = 0;
Inventory _equipped;
Inventory _backpack;
+ Resistances _resistances;
// TODO: Figure out what these are
- Arr58 _arr58;
int _v68, _v69, _v6a, _v6b, _v6c, _v6e, _alignmentCtr;
byte _quest = 0;
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 127d67fb24f..b2651149e12 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -64,7 +64,7 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
};
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
- _mmVal1 = _mmVal2 = _mmVal3 = _mmVal4 = 0;
+ _mmVal1 = _mmVal2 = _resistanceType = _mmVal4 = 0;
// All spell messages start with the monster who casts it
_lines.clear();
@@ -86,7 +86,7 @@ void SpellsMonsters::spell02_energyBlast() {
add(STRING["monster_spells.energy_blast"]);
++_mmVal1;
_mmVal4 = getRandomNumber(16) + 4;
- proc1();
+ damageRandomChar();
}
}
@@ -160,7 +160,7 @@ bool SpellsMonsters::casts() {
}
}
-void SpellsMonsters::proc1() {
+void SpellsMonsters::damageRandomChar() {
chooseCharacter();
handleDamage();
}
@@ -185,7 +185,7 @@ void SpellsMonsters::chooseCharacter() {
}
bool SpellsMonsters::isCharAffected() const {
- int val = g_globals->_currCharacter->_arr58._s._v58 +
+ int val = g_globals->_currCharacter->_resistances._s._magic._current +
g_globals->_spells._s.magic;
return randomThreshold(val);
}
@@ -196,13 +196,13 @@ void SpellsMonsters::handleDamage() {
if (charAffected()) {
if (isEffective()) {
- proc6();
+ if (testElementalResistance()) {
+ if (g_globals->_spells._s.power_shield)
+ _damage = 1;
- if (g_globals->_spells._s.power_shield)
- _damage = 1;
-
- writeDamage();
- subtractDamage();
+ writeDamage();
+ subtractDamage();
+ }
}
}
}
@@ -236,8 +236,38 @@ bool SpellsMonsters::isEffective() {
return true;
}
-void SpellsMonsters::proc6() {
+bool SpellsMonsters::testElementalResistance() {
+ bool result = false;
+
+ switch (_resistanceType) {
+ case RESISTANCE_FIRE:
+ result = damageType1(); break;
+ case RESISTANCE_COLD:
+ result = damageType2(); break;
+ case RESISTANCE_ELECTRICITY:
+ result = damageType3(); break;
+ case RESISTANCE_ACID:
+ result = damageType4(); break;
+ case RESISTANCE_FEAR:
+ result = damageType5(); break;
+ case RESISTANCE_POISON:
+ result = damageType6(); break;
+ case RESISTANCE_PSYCHIC:
+ result = damageType7(); break;
+ default:
+ break;
+ }
+
+ if (!result) {
+ if (_mmVal5) {
+ _damage >>= 2;
+ } else {
+ add(STRING["monster_spells.not_affected"]);
+ return false;
+ }
+ }
+ return true;
}
void SpellsMonsters::writeDamage() {
@@ -291,6 +321,55 @@ void SpellsMonsters::proc9() {
_mmVal7 = randVal < 99 && randVal <= val ? 1 : 0;
}
+bool SpellsMonsters::damageType1() {
+ int threshold = g_globals->_currCharacter->_resistances._s._fire +
+ g_globals->_spells._s.fire;
+ return randomThreshold(threshold);
+}
+
+bool SpellsMonsters::damageType2() {
+ int threshold = g_globals->_currCharacter->_resistances._s._cold +
+ g_globals->_spells._s.cold;
+ return randomThreshold(threshold);
+}
+
+bool SpellsMonsters::damageType3() {
+ int threshold = g_globals->_currCharacter->_resistances._s._electricity +
+ g_globals->_spells._s.electricity;
+ return randomThreshold(threshold);
+}
+
+bool SpellsMonsters::damageType4() {
+ int threshold = g_globals->_currCharacter->_resistances._s._acid +
+ g_globals->_spells._s.acid;
+ return randomThreshold(threshold);
+}
+
+bool SpellsMonsters::damageType5() {
+ if (g_globals->_spells._s.psychic_protection) {
+ return false;
+ } else {
+ int threshold = g_globals->_currCharacter->_resistances._s._fear +
+ g_globals->_spells._s.fear;
+ return randomThreshold(threshold);
+ }
+}
+
+bool SpellsMonsters::damageType6() {
+ int threshold = g_globals->_currCharacter->_resistances._s._poison +
+ g_globals->_spells._s.poison;
+ return randomThreshold(threshold);
+}
+
+bool SpellsMonsters::damageType7() {
+ if (g_globals->_spells._s.psychic_protection) {
+ return false;
+ } else {
+ int threshold = g_globals->_currCharacter->_resistances._s._psychic;
+ return randomThreshold(threshold);
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 88f4c5a1728..90bfb30ae68 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -40,7 +40,7 @@ private:
static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
LineArray _lines;
int _mmVal1 = 0, _mmVal2 = 0;
- int _mmVal3 = 0, _mmVal4 = 0;
+ int _resistanceType = 0, _mmVal4 = 0;
int _mmVal5 = 0, _damage = 0;
int _mmVal7 = 0;
@@ -92,6 +92,11 @@ private:
_lines.back()._text += c;
}
+ /**
+ * Selects a random character and applies the damage to them
+ */
+ void damageRandomChar();
+
/**
* Randomly chooses a character in the party
*/
@@ -130,11 +135,23 @@ private:
*/
void writeDamage();
- void proc1();
- void proc6();
+ /**
+ * Subtracts the damage from the character, making
+ * them unconscious or die if needed
+ */
void subtractDamage();
+
+ bool testElementalResistance();
void proc9();
+ bool damageType1();
+ bool damageType2();
+ bool damageType3();
+ bool damageType4();
+ bool damageType5();
+ bool damageType6();
+ bool damageType7();
+
protected:
virtual bool canMonsterCast() const = 0;
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 0185bc21099..4119a208019 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -106,20 +106,20 @@ void CreateCharacters::NewCharacter::save() {
switch (_race) {
case HUMAN:
- re._arr58._s._v62 = 70;
- re._arr58._s._v66 = 25;
+ re._resistances._s._fear = 70;
+ re._resistances._s._psychic = 25;
break;
case ELF:
- re._arr58._s._v62 = 70;
+ re._resistances._s._fear = 70;
break;
case DWARF:
- re._arr58._s._v64 = 25;
+ re._resistances._s._poison = 25;
break;
case GNOME:
- re._arr58._s._v58 = 20;
+ re._resistances._s._magic = 20;
break;
case HALF_ORC:
- re._arr58._s._v66 = 50;
+ re._resistances._s._psychic = 50;
break;
}
Commit: 4f7c565d22b04eaef078ade1488f09cd92b2a970
https://github.com/scummvm/scummvm/commit/4f7c565d22b04eaef078ade1488f09cd92b2a970
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:14+01:00
Commit Message:
MM: MM1: Beginning to implement monster spells
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/encounter.h
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index e9b6403668d..d7fd29c0868 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -739,6 +739,7 @@ monster_spells:
of_damage: "OF DAMAGE!"
goes_down: "GOES DOWN!!!"
dies: "DIES!"
+ breathes: "BREATHES"
a_curse: "A CURSE"
energy_blast: "ENERGY BLAST"
blindles: "BLINDNESS"
@@ -770,6 +771,18 @@ monster_spells:
energy: "ENERGY"
swarm: "SWARM"
breathes: "BREATHES "
+ effects:
+ 0: "IS SLEPT"
+ 1: "IS BLINDED"
+ 2: "IS SILENCED"
+ 3: "IS DISEASED"
+ 4: "IS POISONED"
+ 5: "IS PARALYZED"
+ 6: "IS RENDERED UNCONSCIOUS"
+ 7: "IS KILLED"
+ 8: "IS TURNED TO STONE"
+ 9: "IS ERADICATED"
+ 10: "IS AFFECTED"
maps:
map00:
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index e9b00332ae1..3261ae63bd5 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -139,7 +139,7 @@ protected:
/**
* Get the monster index
*/
- int getMonsterIndex() const {
+ int getMonsterIndex() const override {
return _monsterIndex;
}
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index d3c6aa5bbc9..0676e245fd4 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -45,7 +45,6 @@ private:
int _monsterNum16 = 0;
int _totalLevels = 0;
int _monsterNum = 0;
- byte _arr1[MAX_COMBAT_MONSTERS];
byte _monsIndexes[MAX_COMBAT_MONSTERS];
void randomAdjust();
@@ -59,6 +58,8 @@ public:
int _highestLevel = 0;
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
+ byte _arr1[MAX_COMBAT_MONSTERS];
+
public:
/**
* Start an encounter
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index b2651149e12..30247ea28ba 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -64,7 +64,8 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
};
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
- _mmVal1 = _mmVal2 = _resistanceType = _mmVal4 = 0;
+ _mmVal1 = _mmVal2 = _newCondition = 0;
+ _resistanceType = RESISTANCE_MAGIC;
// All spell messages start with the monster who casts it
_lines.clear();
@@ -85,14 +86,39 @@ void SpellsMonsters::spell02_energyBlast() {
if (casts()) {
add(STRING["monster_spells.energy_blast"]);
++_mmVal1;
- _mmVal4 = getRandomNumber(16) + 4;
+ _newCondition = getRandomNumber(16) + 4;
damageRandomChar();
}
}
-void SpellsMonsters::spell03_fire() {}
+void SpellsMonsters::spell03_fire() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.fire"].c_str()));
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_FIRE;
-void SpellsMonsters::spell04_blindness() {}
+ int count = g_globals->_encounters._arr1[getMonsterIndex()];
+ _newCondition += count * 6;
+
+ damageRandomChar();
+}
+
+void SpellsMonsters::spell04_blindness() {
+ if (casts()) {
+ add(STRING["monster_spells.blindness"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _newCondition = 2;
+
+ add(':');
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ writeConditionEffect();
+ }
+ }
+}
void SpellsMonsters::spell05_sprayPoison() {}
@@ -192,7 +218,7 @@ bool SpellsMonsters::isCharAffected() const {
void SpellsMonsters::handleDamage() {
_mmVal5 = 1;
- _damage = _mmVal4;
+ _damage = _newCondition;
if (charAffected()) {
if (isEffective()) {
@@ -370,6 +396,47 @@ bool SpellsMonsters::damageType7() {
}
}
+void SpellsMonsters::writeConditionEffect() {
+ _mmVal5 = 0;
+ int effectNum;
+
+ if (!charAffected() || !isEffective() || !testElementalResistance())
+ return;
+
+ if (_newCondition == 0) {
+ effectNum = 10;
+ } else if (_newCondition & BAD_CONDITION) {
+ if (!(_newCondition & (BAD_CONDITION | DEAD)))
+ effectNum = 7;
+ else if (!(_newCondition & (BAD_CONDITION | STONE)))
+ effectNum = 8;
+ else if (_newCondition == ERADICATED)
+ effectNum = 9;
+ else
+ effectNum = 10;
+ } else {
+ effectNum = 0;
+
+ for (byte bitset = _newCondition; bitset & 1;
+ ++effectNum, bitset >>= 1) {
+ }
+ }
+
+ add(STRING[Common::String::format("monster_spells.effects.%d",
+ effectNum)]);
+ add('!');
+}
+
+void SpellsMonsters::setCondition(byte newCondition) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (!(c._condition & BAD_CONDITION)) {
+ c._condition |= newCondition;
+ } else if (newCondition & BAD_CONDITION) {
+ c._condition = newCondition;
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 90bfb30ae68..0b0a5dccf96 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -23,6 +23,7 @@
#define MM1_GAME_SPELLS_MONSTERS
#include "mm/mm1/game/game_logic.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/messages.h"
#include "common/str.h"
@@ -40,9 +41,11 @@ private:
static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
LineArray _lines;
int _mmVal1 = 0, _mmVal2 = 0;
- int _resistanceType = 0, _mmVal4 = 0;
- int _mmVal5 = 0, _damage = 0;
+ byte _newCondition = 0;
+ int _mmVal5 = 0;
int _mmVal7 = 0;
+ Resistance _resistanceType = RESISTANCE_MAGIC;
+ int _damage = 0;
void spell01_curse();
void spell02_energyBlast();
@@ -142,8 +145,10 @@ private:
void subtractDamage();
bool testElementalResistance();
- void proc9();
+ /**
+ * Test whether character resists different damage types
+ */
bool damageType1();
bool damageType2();
bool damageType3();
@@ -152,8 +157,17 @@ private:
bool damageType6();
bool damageType7();
+ /**
+ * Writes different spell effects
+ */
+ void writeConditionEffect();
+
+ void setCondition(byte newCondition);
+ void proc9();
+
protected:
virtual bool canMonsterCast() const = 0;
+ virtual int getMonsterIndex() const = 0;
public:
/**
Commit: 969dbd8bcddf09642ac8000e334849a2c2b6fcac
https://github.com/scummvm/scummvm/commit/969dbd8bcddf09642ac8000e334849a2c2b6fcac
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: Implementing monster spells
Changed paths:
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 30247ea28ba..5a6c541927e 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -111,22 +111,55 @@ void SpellsMonsters::spell04_blindness() {
++_mmVal2;
_newCondition = 2;
- add(':');
-
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- g_globals->_currCharacter = &g_globals->_party[i];
- writeConditionEffect();
- }
+ handlePartyEffects();
}
}
-void SpellsMonsters::spell05_sprayPoison() {}
+void SpellsMonsters::spell05_sprayPoison() {
+ add(STRING["monster_spells.sprays_poison"]);
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_POISON;
+ _newCondition = POISONED;
+ handlePartyEffects();
+}
-void SpellsMonsters::spell06_sprayAcid() {}
+void SpellsMonsters::spell06_sprayAcid() {
+ add(STRING["monster_spells.sprays_acid"]);
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_ACID;
+ _newCondition = getRandomNumber((int)POISONED);
+ add(':');
-void SpellsMonsters::spell07_sleep() {}
+ handlePartyDamage();
+}
-void SpellsMonsters::spell08_paralyze() {}
+void SpellsMonsters::spell07_sleep() {
+ if (casts()) {
+ add(STRING["monster_spells.sleep"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_PSYCHIC;
+ _newCondition = ASLEEP;
+ handlePartyEffects();
+ }
+}
+
+void SpellsMonsters::spell08_paralyze() {
+ if (casts()) {
+ add(STRING["monster_spells.paralyze"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_FEAR;
+ _newCondition = PARALYZED;
+
+ if (g_globals->_encounters._arr1[getMonsterIndex()] >= 5) {
+ handlePartyEffects();
+ } else {
+ chooseCharacter();
+ writeConditionEffect();
+ }
+ }
+}
void SpellsMonsters::spell09_dispell() {}
@@ -437,6 +470,26 @@ void SpellsMonsters::setCondition(byte newCondition) {
}
}
+void SpellsMonsters::handlePartyEffects() {
+ add(':');
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ writeConditionEffect();
+ }
+}
+
+void SpellsMonsters::handlePartyDamage() {
+ Character *tmp = g_globals->_currCharacter;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ handleDamage();
+ }
+
+ g_globals->_currCharacter = tmp;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 0b0a5dccf96..d2f509dead9 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -158,10 +158,20 @@ private:
bool damageType7();
/**
- * Writes different spell effects
+ * Adds different spell effects to the lines
*/
void writeConditionEffect();
+ /**
+ * Adds text for condition effects on the party
+ */
+ void handlePartyEffects();
+
+ /**
+ * Adds text for damage effects on the party
+ */
+ void handlePartyDamage();
+
void setCondition(byte newCondition);
void proc9();
Commit: 5532c67cab6831fb5942487cf5b4294744ff27b8
https://github.com/scummvm/scummvm/commit/5532c67cab6831fb5942487cf5b4294744ff27b8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: More monster spells
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/spells.cpp
engines/mm/mm1/data/spells.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index ce7c3abcaae..854dee5f12a 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -416,7 +416,7 @@ void Character::updateSP() {
_sp = newSP;
}
-void Character::update58() {
+void Character::updateResistances() {
for (int i = 0; i < 8; ++i)
_resistances._arr[i]._current = _resistances._arr[i]._base;
}
@@ -472,7 +472,7 @@ void Character::rest() {
updateSP();
updateAttributes();
updateAC();
- update58();
+ updateResistances();
_condition &= ~(ASLEEP | BLINDED | SILENCED |
PARALYZED | UNCONSCIOUS);
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index df58f62ec56..92f5365f71a 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -308,7 +308,7 @@ struct Character {
*/
void updateSP();
- void update58();
+ void updateResistances();
/**
* Gets a character's condition string
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 0de5126b23d..5195f0510e1 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -84,7 +84,7 @@ void Party::combatDone() {
for (uint i = 0; i < size(); ++i) {
Character &c = (*this)[i];
c.updateAttributes();
- c.update58();
+ c.updateResistances();
if (!(c._condition & BAD_CONDITION))
c._condition &= ~(ASLEEP | SILENCED);
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/data/spells.cpp
index 215354c7827..1a655fde90f 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/data/spells.cpp
@@ -33,6 +33,10 @@
namespace MM {
namespace MM1 {
+void ActiveSpells::clear() {
+ Common::fill(&_arr[0], &_arr[ACTIVE_SPELLS_COUNT], 0);
+}
+
Spells::SpellFn Spells::SPELLS[SPELLS_COUNT] = {
// Cleric spells
placeholder,
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/data/spells.h
index 2ad87d9775c..584178f33f4 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/data/spells.h
@@ -64,6 +64,9 @@ struct ActiveSpellsStruct {
union ActiveSpells {
ActiveSpellsStruct _s;
byte _arr[ACTIVE_SPELLS_COUNT];
+
+ ActiveSpells() { clear(); }
+ void clear();
};
class Spells {
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 88b8069de67..97e63d22ea2 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -196,6 +196,32 @@ bool Combat::canMonsterCast() const {
!(_monsterStatus[_monsterIndex] & (MONFLAG_BLIND | MONFLAG_SILENCED));
}
+void Combat::dispelParty() {
+ g_globals->_spells.clear();
+ Character *tmpC = g_globals->_currCharacter;
+ Monster *tmpM = _monsterP;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ c.updateAttributes();
+ c.updateAC();
+ c.updateResistances();
+
+ if (!(c._condition & BAD_CONDITION))
+ c._condition &= ~(BLINDED | SILENCED);
+ }
+
+ g_globals->_currCharacter = tmpC;
+
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ monsterSetPtr(i);
+ _monsterStatus[i] = 0;
+ }
+
+ _monsterP = tmpM;
+}
+
void Combat::combatLoop() {
if (_monsterIndex != 0) {
selectParty();
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3261ae63bd5..dabdb441321 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -127,8 +127,23 @@ protected:
/*------- Inherited virtual methods ------*/
+ /**
+ * Get the monster index
+ */
+ int getMonsterIndex() const override {
+ return _monsterIndex;
+ }
+
+ /**
+ * Returns true if a monster can cast certain spells
+ */
bool canMonsterCast() const override;
+ /**
+ * Dispels any effects on the party
+ */
+ void dispelParty() override;
+
/*------- combat execution ------*/
/**
@@ -136,13 +151,6 @@ protected:
*/
void combatLoop();
- /**
- * Get the monster index
- */
- int getMonsterIndex() const override {
- return _monsterIndex;
- }
-
/**
* Select treasure for a defeated monster
*/
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 5a6c541927e..b0711a53beb 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -37,7 +37,7 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
&SpellsMonsters::spell06_sprayAcid,
&SpellsMonsters::spell07_sleep,
&SpellsMonsters::spell08_paralyze,
- &SpellsMonsters::spell09_dispell,
+ &SpellsMonsters::spell09_dispel,
&SpellsMonsters::spell10_lightningBolt,
&SpellsMonsters::spell11_strangeGas,
&SpellsMonsters::spell12_explode,
@@ -161,13 +161,48 @@ void SpellsMonsters::spell08_paralyze() {
}
}
-void SpellsMonsters::spell09_dispell() {}
+void SpellsMonsters::spell09_dispel() {
+ if (casts()) {
+ add(STRING["monster_spells.dispel"]);
+ dispelParty();
+ }
+}
+
+void SpellsMonsters::spell10_lightningBolt() {
+ if (casts()) {
+ add(STRING["monster_spells.lightning_bolt"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_ELECTRICITY;
+ _newCondition = getRandomNumber(37) + 5;
+ damageRandomChar();
+ }
+}
+
+void SpellsMonsters::spell11_strangeGas() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.strange_gas"].c_str()));
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_POISON;
+ _newCondition = BAD_CONDITION | STONE;
-void SpellsMonsters::spell10_lightningBolt() {}
+ handlePartyEffects();
+}
-void SpellsMonsters::spell11_strangeGas() {}
+void SpellsMonsters::spell12_explode() {
+ /*
+ add(STRING["monster_spells.explode"]);
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_POISON;
+ _newCondition = getRandomNumber(_arr1[getMonsterIndex()]);
+ _arr1[getMonsterIndex()] = 0;
+ removeMonster();
-void SpellsMonsters::spell12_explode() {}
+ add(':');
+ handlePartyDamage();
+ */
+}
void SpellsMonsters::spell13_fireball() {}
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index d2f509dead9..2b595be3856 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -55,7 +55,7 @@ private:
void spell06_sprayAcid();
void spell07_sleep();
void spell08_paralyze();
- void spell09_dispell();
+ void spell09_dispel();
void spell10_lightningBolt();
void spell11_strangeGas();
void spell12_explode();
@@ -178,6 +178,7 @@ private:
protected:
virtual bool canMonsterCast() const = 0;
virtual int getMonsterIndex() const = 0;
+ virtual void dispelParty() = 0;
public:
/**
Commit: 439611f707b02a28ae2bb475a0ce278a72a578eb
https://github.com/scummvm/scummvm/commit/439611f707b02a28ae2bb475a0ce278a72a578eb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: Remaining monster spell methods
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index d7fd29c0868..008b3959551 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -748,20 +748,20 @@ monster_spells:
sleep: "SLEEP"
paralyze: "PARALYZE"
dispel: "DISPEL"
- lightningBolt: "LIGHTNING BOLT"
- strangeGas: "STRANGE GAS"
+ lightning_bolt: "LIGHTNING BOLT"
+ strang_gGas: "STRANGE GAS"
explode: "EXPLODE"
fireball: "FIREBALL"
gazes: "GAZES"
- acidArrow: "ACID ARROW"
+ acid_arrow: "ACID ARROW"
calls_elements: "CALLS UPPON THE ELEMENTS"
- coldBeam: "COLD BEAM"
- dancingSword: "DANCING SWORD"
- magicDrain: "MAGIC DRAIN"
- fingerOfDeath: "FINGER OF DEATH"
- sunRay: "SUN RAY"
+ cold_beam: "COLD BEAM"
+ dancing_sword: "DANCING SWORD"
+ magic_drain: "MAGIC DRAIN"
+ finger_of_death: "FINGER OF DEATH"
+ sun_ray: "SUN RAY"
disintegration: "DISINTEGRATION"
- commandsEnergy: "COMMANDS ENERGY"
+ commands_energy: "COMMANDS ENERGY"
poison: "POISON"
lightning: "LIGHTNING"
frost: "FROST"
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index dabdb441321..1658ef18b87 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -43,7 +43,6 @@ protected:
byte _arr2[MAX_COMBAT_MONSTERS];
int _arr3[MAX_PARTY_SIZE / 2];
byte _arr4[MAX_COMBAT_MONSTERS];
- byte _monsterStatus[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
bool _treasureFlags[MAX_PARTY_SIZE];
int _val1;
@@ -144,6 +143,8 @@ protected:
*/
void dispelParty() override;
+ void removeMonster() override;
+
/*------- combat execution ------*/
/**
@@ -194,7 +195,6 @@ protected:
void monsterAdvances();
bool monsterChanges();
void proc2();
- void removeMonster();
void checkParty();
};
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index b0711a53beb..8905591d0f5 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -42,7 +42,7 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
&SpellsMonsters::spell11_strangeGas,
&SpellsMonsters::spell12_explode,
&SpellsMonsters::spell13_fireball,
- &SpellsMonsters::spell14_fire2,
+ &SpellsMonsters::spell14_fireBreath,
&SpellsMonsters::spell15_gazes,
&SpellsMonsters::spell16_acidArrow,
&SpellsMonsters::spell17_elements,
@@ -63,6 +63,11 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
&SpellsMonsters::spell32_swarm
};
+SpellsMonsters::SpellsMonsters() {
+ Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
+}
+
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
_mmVal1 = _mmVal2 = _newCondition = 0;
_resistanceType = RESISTANCE_MAGIC;
@@ -191,58 +196,243 @@ void SpellsMonsters::spell11_strangeGas() {
}
void SpellsMonsters::spell12_explode() {
- /*
add(STRING["monster_spells.explode"]);
++_mmVal2;
_resistanceType = RESISTANCE_POISON;
_newCondition = getRandomNumber(_arr1[getMonsterIndex()]);
_arr1[getMonsterIndex()] = 0;
+ _monsterStatus[getMonsterIndex()] = MONFLAG_DEAD;
removeMonster();
add(':');
handlePartyDamage();
- */
}
-void SpellsMonsters::spell13_fireball() {}
+void SpellsMonsters::spell13_fireball() {
+ if (casts()) {
+ add(STRING["monster_spells.fireball"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_FIRE;
-void SpellsMonsters::spell14_fire2() {}
+ // This whole condition choice makes no sense
+ _newCondition += 6 *
+ g_globals->_encounters._arr1[getMonsterIndex()];
+ _newCondition = getRandomNumber(_newCondition) + 4;
-void SpellsMonsters::spell15_gazes() {}
+ add(':');
+ handlePartyDamage();
+ }
+}
-void SpellsMonsters::spell16_acidArrow() {}
+void SpellsMonsters::spell14_fireBreath() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.fire"].c_str()));
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_FIRE;
-void SpellsMonsters::spell17_elements() {}
+ // This whole condition choice makes no sense
+ _newCondition += 8 *
+ g_globals->_encounters._arr1[getMonsterIndex()];
+ _newCondition = getRandomNumber(_newCondition);
-void SpellsMonsters::spell18_coldBeam() {}
+ add(':');
+ handlePartyDamage();
+}
-void SpellsMonsters::spell19_dancingSword() {}
+void SpellsMonsters::spell15_gazes() {
+ add(STRING["monster_spells.gazes"]);
+ ++_mmVal2;
+ _newCondition = BAD_CONDITION | STONE;
-void SpellsMonsters::spell20_magicDrain() {}
+ chooseCharacter();
+ writeConditionEffect();
+}
-void SpellsMonsters::spell21_fingerOfDeath() {}
+void SpellsMonsters::spell16_acidArrow() {
+ add(STRING["monster_spells.acid_arrow"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_ACID;
+ _newCondition = getRandomNumber(31) + 9;
-void SpellsMonsters::spell22_sunRay() {}
+ damageRandomChar();
+}
-void SpellsMonsters::spell23_disintegration() {}
+void SpellsMonsters::spell17_elements() {
+ add(STRING["monster_spells.call_elements"]);
+ ++_mmVal2;
+ _newCondition = getRandomNumber(21) + 39;
-void SpellsMonsters::spell24_commandsEnergy() {}
+ damageRandomChar();
+}
-void SpellsMonsters::spell25_poison() {}
+void SpellsMonsters::spell18_coldBeam() {
+ if (casts()) {
+ add(STRING["monster_spells.cold_beam"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _resistanceType = RESISTANCE_COLD;
+ _newCondition = getRandomNumber(41) + 9;
-void SpellsMonsters::spell26_lightning() {}
+ damageRandomChar();
+ }
+}
-void SpellsMonsters::spell27_frost() {}
+void SpellsMonsters::spell19_dancingSword() {
+ if (casts()) {
+ add(STRING["monster_spells.dancing_sword"]);
+ ++_mmVal1;
+ _newCondition = getRandomNumber(14) + 16;
+
+ add(':');
+ handlePartyDamage();
+ }
+}
+
+void SpellsMonsters::spell20_magicDrain() {
+ add(STRING["monster_spells.magic_drain"]);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ c._sp._current = 0;
+ }
+
+ dispelParty();
+}
+
+void SpellsMonsters::spell21_fingerOfDeath() {
+ if (casts()) {
+ add(STRING["monster_spells.finger_of_death"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _newCondition = BAD_CONDITION | DEAD;
+
+ chooseCharacter();
+ writeConditionEffect();
+ }
+}
-void SpellsMonsters::spell28_spikes() {}
+void SpellsMonsters::spell22_sunRay() {
+ if (casts()) {
+ add(STRING["monster_spells.sun_ray"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _newCondition = getRandomNumber(51) + 49;
-void SpellsMonsters::spell29_acid() {}
+ damageRandomChar();
+ }
+}
-void SpellsMonsters::spell30_fire() {}
+void SpellsMonsters::spell23_disintegration() {
+ if (casts()) {
+ add(STRING["monster_spells.disintegration"]);
+ ++_mmVal1;
+ ++_mmVal2;
+ _newCondition = ERADICATED;
-void SpellsMonsters::spell31_energy() {}
+ chooseCharacter();
+ writeConditionEffect();
+ }
+}
-void SpellsMonsters::spell32_swarm() {}
+void SpellsMonsters::spell24_commandsEnergy() {
+ add(STRING["monster_spells.commands_energy"]);
+ _newCondition = SILENCED | PARALYZED | UNCONSCIOUS;
+ damageRandomChar();
+}
+
+void SpellsMonsters::spell25_poison() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.poison"].c_str()));
+ _resistanceType = RESISTANCE_POISON;
+ _newCondition = _arr1[getMonsterIndex()];
+ ++_mmVal2;
+
+ add(':');
+ handlePartyDamage();
+}
+
+void SpellsMonsters::spell26_lightning() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.lightning"].c_str()));
+ _resistanceType = RESISTANCE_ELECTRICITY;
+ _newCondition = _arr1[getMonsterIndex()];
+ ++_mmVal2;
+
+ add(':');
+ handlePartyDamage();
+}
+
+void SpellsMonsters::spell27_frost() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.frost"].c_str()));
+ _resistanceType = RESISTANCE_COLD;
+ _newCondition = _arr1[getMonsterIndex()];
+ ++_mmVal2;
+
+ add(':');
+ handlePartyDamage();
+}
+
+void SpellsMonsters::spell28_spikes() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.spikes"].c_str()));
+ _resistanceType = RESISTANCE_ELECTRICITY;
+ _newCondition = _arr1[getMonsterIndex()];
+ ++_mmVal2;
+
+ add(':');
+ handlePartyDamage();
+}
+
+void SpellsMonsters::spell29_acid() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.acid"].c_str()));
+ _resistanceType = RESISTANCE_ACID;
+ _newCondition = _arr1[getMonsterIndex()];
+ ++_mmVal2;
+
+ add(':');
+ handlePartyDamage();
+}
+
+void SpellsMonsters::spell30_fire() {
+ add(Common::String::format("%s %s",
+ STRING["monster_spells.breathes"].c_str(),
+ STRING["monster_spells.fire"].c_str()));
+ _resistanceType = RESISTANCE_FIRE;
+ _newCondition = _arr1[getMonsterIndex()];
+ ++_mmVal2;
+
+ add(':');
+ handlePartyDamage();
+}
+
+void SpellsMonsters::spell31_energy() {
+ add(STRING["monster_spells.energy"]);
+ _newCondition = _arr1[getMonsterIndex()];
+ ++_mmVal2;
+
+ add(':');
+ handlePartyDamage();
+}
+
+void SpellsMonsters::spell32_swarm() {
+ add(STRING["monster_spells.swarm"]);
+ ++_mmVal2;
+ _newCondition = getRandomNumber(12);
+
+ add(':');
+ handlePartyDamage();
+}
bool SpellsMonsters::casts() {
if (canMonsterCast()) {
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 2b595be3856..ba4e26610e2 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -31,6 +31,7 @@ namespace MM {
namespace MM1 {
namespace Game {
+#define MAX_COMBAT_MONSTERS 15
#define MONSTER_SPELLS_COUNT 32
class SpellsMonsters;
@@ -60,7 +61,7 @@ private:
void spell11_strangeGas();
void spell12_explode();
void spell13_fireball();
- void spell14_fire2();
+ void spell14_fireBreath();
void spell15_gazes();
void spell16_acidArrow();
void spell17_elements();
@@ -176,11 +177,17 @@ private:
void proc9();
protected:
+ byte _arr1[MAX_COMBAT_MONSTERS];
+ byte _monsterStatus[MAX_COMBAT_MONSTERS];
+
virtual bool canMonsterCast() const = 0;
virtual int getMonsterIndex() const = 0;
virtual void dispelParty() = 0;
+ virtual void removeMonster() = 0;
public:
+ SpellsMonsters();
+
/**
* Monster casts a spell
*/
Commit: 43f1507bdc5dc8cb21d9880c04dea5674f85e1e9
https://github.com/scummvm/scummvm/commit/43f1507bdc5dc8cb21d9880c04dea5674f85e1e9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: Adding display for monster spell results
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 97e63d22ea2..054eae55c1e 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -592,8 +592,11 @@ void Combat::checkMonsterSpells() {
if (!_monsterP->_field1c || _monsterP->_field1c >= 33) {
checkMonsterActions();
} else {
- // TODO: Monsters spell casting?
+ castMonsterSpell(_monsterList[_monsterIndex]._name,
+ _monsterP->_field1c);
+ setMode(MONSTER_SPELL);
}
+ return;
}
}
}
@@ -635,7 +638,14 @@ void Combat::checkParty() {
return;
}
+ // Update the array for the party
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if ((c._condition & BAD_CONDITION) || !c._hpBase)
+ _arr3[i] = 1;
+ }
+ loop1();
}
} // namespace Game
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 1658ef18b87..29a683e461a 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -67,7 +67,7 @@ protected:
enum Mode {
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
- MONSTER_FLEES, MONSTER_WANDERS
+ MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL
};
Mode _mode = SELECT_OPTION;
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 8905591d0f5..8d10fcccbcf 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -444,6 +444,14 @@ bool SpellsMonsters::casts() {
}
}
+void SpellsMonsters::addCharName() {
+ // Wrap name in special characters so that characters
+ // with multiple word names will capitalize each word
+ // of the name
+ add(Common::String("|%s|",
+ g_globals->_currCharacter->_name));
+}
+
void SpellsMonsters::damageRandomChar() {
chooseCharacter();
handleDamage();
@@ -492,8 +500,9 @@ void SpellsMonsters::handleDamage() {
}
bool SpellsMonsters::charAffected() {
- _lines.push_back(Line(0, 2, Common::String::format("%s ",
- g_globals->_currCharacter->_name)));
+ _lines.push_back(Line(0, 2, ""));
+ addCharName();
+ add(' ');
if (_mmVal1 && !isCharAffected()) {
_lines.back()._text += STRING["monster_spells.not_affected"];
@@ -578,7 +587,7 @@ void SpellsMonsters::subtractDamage() {
if (!(c._condition & (BAD_CONDITION | UNCONSCIOUS))) {
c._condition |= UNCONSCIOUS;
- add(c._name);
+ addCharName();
add(' ');
add(STRING["monster_spells.goes_down"]);
Sound::sound2(SOUND_8);
@@ -587,9 +596,10 @@ void SpellsMonsters::subtractDamage() {
if (c._condition & BAD_CONDITION)
c._condition = BAD_CONDITION | DEAD;
- _lines.push_back(Line(0, _lines.back().y + 1,
- Common::String::format("%s %s",
- c._name, STRING["monster_spells.dies"].c_str())));
+ _lines.push_back(Line(0, 3, ""));
+ addCharName();
+ add(' ');
+ add(STRING["monster_spells.dies"]);
Sound::sound2(SOUND_8);
}
}
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index ba4e26610e2..ef7de69fc4b 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -96,6 +96,11 @@ private:
_lines.back()._text += c;
}
+ /**
+ * Adds current character's name
+ */
+ void addCharName();
+
/**
* Selects a random character and applies the damage to them
*/
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 344cd877469..5c31648e035 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -34,6 +34,11 @@ Combat::Combat() : TextView("Combat") {
void Combat::setMode(Mode newMode) {
_mode = newMode;
+
+ if (_mode == MONSTER_SPELL)
+ // Make a copy of monster spell
+ _monsterSpellLines = getMonsterSpellMessage();
+
redraw();
}
@@ -79,6 +84,10 @@ void Combat::draw() {
writeMonsterAction();
delaySeconds(3);
return;
+ case MONSTER_SPELL:
+ writeMonsterSpell();
+ delaySeconds(2);
+ return;
default:
break;
}
@@ -127,6 +136,9 @@ void Combat::timeout() {
writeMonsters();
checkParty();
return;
+ case MONSTER_SPELL:
+ checkMonsterSpellDone();
+ return;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_spells;
spells._s.bless = 0;
@@ -377,6 +389,37 @@ void Combat::writeMonsterAction() {
writeString(STRING["dialogs.combat.monster_flees"]);
}
+void Combat::writeMonsterSpell() {
+ resetBottom();
+
+ for (int i = 0, y = 0; i < _monsterSpellLines.size() &&
+ _monsterSpellLines[i].y > y;
+ y = _monsterSpellLines[i].y, ++i) {
+ Common::String text = _monsterSpellLines[i]._text;
+ size_t idx;
+ while ((idx = text.findFirstOf(' ')) != Common::String::npos)
+ text.deleteChar(idx);
+
+ writeString(0, _monsterSpellLines[i].y, text);
+ }
+}
+
+void Combat::checkMonsterSpellDone() {
+ for (uint i = 0; i < _monsterSpellLines.size(); ++i) {
+ if (i > 0 && _monsterSpellLines[i].y ==
+ _monsterSpellLines[i - 1].y) {
+ // Remove the message line just displayed, and redraw
+ // so the next one can be shown
+ _monsterSpellLines.remove_at(i - 1);
+ redraw();
+ return;
+ }
+ }
+
+ checkParty();
+}
+
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 0b323338ce1..a57d74d8de8 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -31,6 +31,8 @@ namespace Views {
class Combat : public TextView, public Game::Combat {
private:
+ LineArray _monsterSpellLines;
+
void writeOptions();
void writeAttackOptions();
void writeCastOption();
@@ -100,6 +102,16 @@ private:
*/
void writeMonsterAction();
+ /**
+ * Write out message from a monster casting a spell
+ */
+ void writeMonsterSpell();
+
+ /**
+ * Whether there's messages remaining
+ */
+ void checkMonsterSpellDone();
+
protected:
/**
* Sets a new display mode
Commit: bb0114e6b27ccfb5744f66133bcb79ca816a8d05
https://github.com/scummvm/scummvm/commit/bb0114e6b27ccfb5744f66133bcb79ca816a8d05
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: In progress attack code
Changed paths:
engines/mm/mm1/data/character.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/meta_engine.cpp
engines/mm/mm1/meta_engine.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 92f5365f71a..34c8f42db54 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -242,7 +242,8 @@ struct Character {
Resistances _resistances;
// TODO: Figure out what these are
- int _v68, _v69, _v6a, _v6b, _v6c, _v6e, _alignmentCtr;
+ AttributePair _physicalAttr, _missileAttr;
+ int _v6c, _v6e, _alignmentCtr;
byte _quest = 0;
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 054eae55c1e..06a653ae4e5 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -43,6 +43,8 @@ void Combat::clear() {
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_val6 = _val7 = 0;
_val8 = _val9 = _val10 = 0;
+ _val11 = _val12 = 0;
+ _attackerLevel = 0;
_advanceIndex = 0;
_handicap1 = _handicap2 = 0;
_handicap3 = _handicap4 = 0;
@@ -53,6 +55,8 @@ void Combat::clear() {
_totalExperience = 0;
_advanceIndex = 0;
_monstersResistSpells = _monstersRegenerate = false;
+ _attackAttr1.clear();
+ _attackAttr2.clear();
// TODO: clear everything
@@ -648,6 +652,101 @@ void Combat::checkParty() {
loop1();
}
+void Combat::attackMonster68() {
+ _attackAttr1 = g_globals->_currCharacter->_physicalAttr;
+ attackMonster(0);
+}
+
+void Combat::attackMonster6a() {
+ _attackAttr1 = g_globals->_currCharacter->_missileAttr;
+ attackMonster(0);
+}
+
+void Combat::attackMonster(int monsterNum) {
+ monsterSetPtr(0);
+
+ Character &c = *g_globals->_currCharacter;
+ _attackerLevel = c._level._current;
+
+ if (c._class >= CLERIC) {
+ _attackerLevel >>= 1;
+ if (c._class == SORCERER)
+ _attackerLevel >>= 1;
+ }
+
+ // Affect level based on accuracy
+ _attackerLevel += _attackAttr1;
+
+ if (c._accuracy >= 40)
+ _attackerLevel += 7;
+ else if (c._accuracy >= 35)
+ _attackerLevel += 6;
+ else if (c._accuracy >= 30)
+ _attackerLevel += 5;
+ else if (c._accuracy >= 24)
+ _attackerLevel += 4;
+ else if (c._accuracy >= 19)
+ _attackerLevel += 3;
+ else if (c._accuracy >= 16)
+ _attackerLevel += 2;
+ else if (c._accuracy >= 23)
+ _attackerLevel += 1;
+ else if (c._accuracy >= 9)
+ _attackerLevel += 0;
+ else if (c._accuracy >= 7)
+ _attackerLevel = MAX((int)_attackerLevel - 1, 0);
+ else if (c._accuracy >= 5)
+ _attackerLevel = MAX((int)_attackerLevel - 2, 0);
+ else
+ _attackerLevel = MAX((int)_attackerLevel - 3, 0);
+
+ _val12 = 1;
+
+ if (c._class >= CLERIC && c._level >= 8) {
+ _val12 += c._level / 8;
+ }
+
+ // Affect level based on might
+ _attackAttr2 = _attackAttr1;
+
+ if (c._might >= 40)
+ _attackAttr2._current += 13;
+ else if (c._might >= 35)
+ _attackAttr2._current += 12;
+ else if (c._might >= 29)
+ _attackAttr2._current += 11;
+ else if (c._might >= 27)
+ _attackAttr2._current += 10;
+ else if (c._might >= 25)
+ _attackAttr2._current += 9;
+ else if (c._might >= 23)
+ _attackAttr2._current += 8;
+ else if (c._might >= 21)
+ _attackAttr2._current += 7;
+ else if (c._might >= 19)
+ _attackAttr2._current += 6;
+ else if (c._might >= 18)
+ _attackAttr2._current += 5;
+ else if (c._might >= 17)
+ _attackAttr2._current += 4;
+ else if (c._might >= 16)
+ _attackAttr2._current += 3;
+ else if (c._might >= 15)
+ _attackAttr2._current += 2;
+ else if (c._might >= 13)
+ _attackAttr2._current += 1;
+ else if (c._might >= 9)
+ _attackAttr2._current += 0;
+ else if (c._might >= 7)
+ _attackAttr2._current = MAX((int)_attackAttr2._current - 1, 0);
+ else if (c._might >= 5)
+ _attackAttr2._current = MAX((int)_attackAttr2._current - 2, 0);
+ else
+ _attackAttr2._current = MAX((int)_attackAttr2._current - 3, 0);
+
+ // TODO: attack message and further stuff
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 29a683e461a..9b0cfecd0a8 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -51,6 +51,8 @@ protected:
char _val2, _val3, _val4, _val5;
byte _val6, _val7;
int _val8, _val9, _val10;
+ int _val11, _val12;
+ int _attackerLevel;
int _advanceIndex;
int _handicap1, _handicap2;
int _handicap3, _handicap4;
@@ -59,6 +61,7 @@ protected:
Common::String _monsterName;
bool _monstersResistSpells;
bool _monstersRegenerate;
+ AttributePair _attackAttr1, _attackAttr2;
enum Handicap {
HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
HANDICAP_MONSTER = 2
@@ -196,6 +199,13 @@ protected:
bool monsterChanges();
void proc2();
void checkParty();
+
+ /**
+ * Attack a monster
+ */
+ void attackMonster68();
+ void attackMonster6a();
+ void attackMonster(int monsterNum);
};
} // namespace Game
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index 5b4d69132dd..fd675e78d45 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -51,6 +51,18 @@ static const KeybindingRecord PARTY_KEYS[] = {
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
};
+static const KeybindingRecord COMBAT_KEYS[] = {
+ { KEYBIND_COMBAT_ATTACK, "COMBAT_ATTACK", "Attack", "A", nullptr },
+ { KEYBIND_COMBAT_BLOCK, "COMBAT_BLOCK", "Block", "B", nullptr },
+ { KEYBIND_COMBAT_CAST, "COMBAT_CAST", "Cast", "C", nullptr },
+ { KEYBIND_COMBAT_EXCHANGE, "COMBAT_EXCHANGE", "Exchange", "E", nullptr },
+ { KEYBIND_COMBAT_FIGHT, "COMBAT_FIGHT", "Fight", "F", nullptr },
+ { KEYBIND_COMBAT_RETREAT, "COMBAT_RETREAT", "Retreat", "R", nullptr },
+ { KEYBIND_COMBAT_SHOOT, "COMBAT_SHOOT", "Shoot", "S", nullptr },
+ { KEYBIND_COMBAT_USE, "COMBAT_USE", "Use", "U", nullptr },
+ { KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
+};
+
static const KeybindingRecord NORMAL_KEYS[] = {
{ KEYBIND_FORWARDS, "FORWARDS", "Forwards", "UP", nullptr },
{ KEYBIND_BACKWARDS, "BACKWARDS", "Backwards", "DOWN", nullptr },
@@ -93,6 +105,12 @@ static const KeysRecord PARTY_MENU_RECORDS[] = {
{ nullptr, nullptr, nullptr }
};
+static const KeysRecord COMBAT_MENU_RECORDS[] = {
+ { "mm1_combat", "Might and Magic 1 - Combat", COMBAT_KEYS },
+ { "mm1_party", "Might and Magic 1 - Party", PARTY_KEYS },
+ { nullptr, nullptr, nullptr }
+};
+
static const KeysRecord NORMAL_RECORDS[] = {
{ "mm1", "Might and Magic 1", NORMAL_KEYS },
{ "mm1_party", "Might and Magic 1 - Party", PARTY_KEYS },
@@ -100,9 +118,10 @@ static const KeysRecord NORMAL_RECORDS[] = {
{ nullptr, nullptr, nullptr }
};
-static const KeysRecord *MODE_RECORDS[4] = {
+static const KeysRecord *MODE_RECORDS[5] = {
MENU_RECORDS,
PARTY_MENU_RECORDS,
+ COMBAT_MENU_RECORDS,
NORMAL_RECORDS,
nullptr // TODO: combat keybindings
};
diff --git a/engines/mm/mm1/meta_engine.h b/engines/mm/mm1/meta_engine.h
index d092acd8d27..c336b201013 100644
--- a/engines/mm/mm1/meta_engine.h
+++ b/engines/mm/mm1/meta_engine.h
@@ -54,6 +54,23 @@ enum KeybindingAction {
KEYBIND_VIEW_PARTY5,
KEYBIND_VIEW_PARTY6,
+ // Encounters
+ KEYBIND_ATTACK,
+ KEYBIND_BRIBE,
+ KEYBIND_RETREAT,
+ KEYBIND_SURRENDER,
+
+ // Combat
+ KEYBIND_COMBAT_ATTACK,
+ KEYBIND_COMBAT_BLOCK,
+ KEYBIND_COMBAT_CAST,
+ KEYBIND_COMBAT_EXCHANGE,
+ KEYBIND_COMBAT_FIGHT,
+ KEYBIND_COMBAT_RETREAT,
+ KEYBIND_COMBAT_SHOOT,
+ KEYBIND_COMBAT_USE,
+
+ // Cheats
KEYBIND_CHEAT_COLLISIONS, KEYBIND_CHEAT_DESTROY,
KEYBIND_CHEAT_DESTROY_CREATURES, KEYBIND_CHEAT_EQUIPMENT,
KEYBIND_CHEAT_FLEE, KEYBIND_CHEAT_GOTO, KEYBIND_CHEAT_HELP,
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 3384a7631ab..8b11da6ee76 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -355,15 +355,12 @@ void CharacterInfo::equipItem(uint index) {
switch (getItemCategory(itemId)) {
case ITEMCAT_WEAPON:
case ITEMCAT_TWO_HANDED:
- c._v68 = item._val16;
- c._v69 = item._val17;
+ c._physicalAttr._base = item._val16;
+ c._physicalAttr._current = item._val17;
break;
case ITEMCAT_MISSILE:
- c._v6a = item._val16;
- c._v6b = item._val17;
- break;
- c._v68 = item._val16;
- c._v69 = item._val17;
+ c._missileAttr._base = item._val16;
+ c._missileAttr._current = item._val17;
break;
case ITEMCAT_ARMOR:
case ITEMCAT_SHIELD:
@@ -432,10 +429,10 @@ void CharacterInfo::removeItem(uint index) {
switch (getItemCategory(itemId)) {
case ITEMCAT_WEAPON:
case ITEMCAT_TWO_HANDED:
- c._v68 = c._v69 = 0;
+ c._physicalAttr.clear();
break;
case ITEMCAT_MISSILE:
- c._v6a = c._v6b = 0;
+ c._missileAttr.clear();
break;
case ITEMCAT_ARMOR:
case ITEMCAT_SHIELD:
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 5c31648e035..c5c26553198 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -46,6 +46,8 @@ bool Combat::msgFocus(const FocusMessage &msg) {
// Clear combat data
clear();
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
+
_monstersCount = _monsterList.size();
_party.clear();
for (uint i = 0; i < g_globals->_party.size(); ++i)
@@ -60,6 +62,11 @@ bool Combat::msgFocus(const FocusMessage &msg) {
return true;
}
+bool Combat::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return TextView::msgUnfocus(msg);
+}
+
void Combat::draw() {
switch (_mode) {
case NEXT_ROUND:
@@ -92,7 +99,6 @@ void Combat::draw() {
break;
}
-
clearSurface();
writeStaticContent();
writeHandicap();
@@ -161,8 +167,53 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
return true;
}
+bool Combat::msgAction(const ActionMessage &msg) {
+ if (_mode != SELECT_OPTION || _option != OPTION_NONE)
+ return false;
+
+ switch (msg._action) {
+ case KEYBIND_COMBAT_ATTACK:
+ attack();
+ break;
+ case KEYBIND_COMBAT_BLOCK:
+ block();
+ break;
+ case KEYBIND_COMBAT_CAST:
+ cast();
+ break;
+ case KEYBIND_COMBAT_EXCHANGE:
+ exchange();
+ break;
+ case KEYBIND_COMBAT_FIGHT:
+ fight();
+ break;
+ case KEYBIND_COMBAT_RETREAT:
+ retreat();
+ break;
+ case KEYBIND_COMBAT_SHOOT:
+ shoot();
+ break;
+ case KEYBIND_COMBAT_USE:
+ use();
+ break;
+ default:
+ break;
+ }
+}
+
void Combat::writeOptions() {
resetBottom();
+
+ switch (_option) {
+ case OPTION_NONE:
+ writeAllOptions();
+ break;
+ default:
+ break;
+ }
+}
+
+void Combat::writeAllOptions() {
writeString(0, 20, STRING["dialogs.combat.options_for"]);
writeString(0, 22, g_globals->_currCharacter->_name);
@@ -198,7 +249,7 @@ void Combat::writeOptions() {
// Archers can always attack
canAttack = g_globals->_currCharacter->_class == ARCHER;
}
- if (canAttack && g_globals->_currCharacter->_v6a) {
+ if (canAttack && g_globals->_currCharacter->_missileAttr) {
_val3 = 'S';
writeShootOption();
}
@@ -392,7 +443,7 @@ void Combat::writeMonsterAction() {
void Combat::writeMonsterSpell() {
resetBottom();
- for (int i = 0, y = 0; i < _monsterSpellLines.size() &&
+ for (uint i = 0, y = 0; i < _monsterSpellLines.size() &&
_monsterSpellLines[i].y > y;
y = _monsterSpellLines[i].y, ++i) {
Common::String text = _monsterSpellLines[i]._text;
@@ -419,6 +470,33 @@ void Combat::checkMonsterSpellDone() {
checkParty();
}
+void Combat::attack() {
+ if (_val5 == 32)
+ return;
+
+ attackMonster(0);
+}
+
+void Combat::block() {
+}
+
+void Combat::cast() {
+}
+
+void Combat::exchange() {
+}
+
+void Combat::fight() {
+}
+
+void Combat::retreat() {
+}
+
+void Combat::shoot() {
+}
+
+void Combat::use() {
+}
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index a57d74d8de8..7cbec5d50a3 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -32,8 +32,14 @@ namespace Views {
class Combat : public TextView, public Game::Combat {
private:
LineArray _monsterSpellLines;
+ // Combat options that have sub-option selection
+ enum SelectedOption {
+ OPTION_NONE, OPTION_ATTACK
+ };
+ SelectedOption _option = OPTION_NONE;
void writeOptions();
+ void writeAllOptions();
void writeAttackOptions();
void writeCastOption();
void writeShootOption();
@@ -112,6 +118,46 @@ private:
*/
void checkMonsterSpellDone();
+ /**
+ * Attack option
+ */
+ void attack();
+
+ /**
+ * Block option
+ */
+ void block();
+
+ /**
+ * Cast option
+ */
+ void cast();
+
+ /**
+ * Exchange option
+ */
+ void exchange();
+
+ /**
+ * Fight option
+ */
+ void fight();
+
+ /**
+ * Retreat option
+ */
+ void retreat();
+
+ /**
+ * Shoot option
+ */
+ void shoot();
+
+ /**
+ * Use option
+ */
+ void use();
+
protected:
/**
* Sets a new display mode
@@ -126,6 +172,11 @@ public:
*/
bool msgFocus(const FocusMessage &msg) override;
+ /**
+ * Called when the view is unfocused
+ */
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+
/**
* Draw the Combat details overlayed on
* the existing game screen
@@ -141,6 +192,11 @@ public:
* Handles keypresses
*/
bool msgKeypress(const KeypressMessage &msg) override;
+
+ /**
+ * Key binder actions
+ */
+ bool msgAction(const ActionMessage &msg) override;
};
} // namespace Views
Commit: c10035f06439445b6f4a137cae5e5ba3928055e8
https://github.com/scummvm/scummvm/commit/c10035f06439445b6f4a137cae5e5ba3928055e8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: Method name renaming
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 06a653ae4e5..d2a1cd5362e 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -57,6 +57,7 @@ void Combat::clear() {
_monstersResistSpells = _monstersRegenerate = false;
_attackAttr1.clear();
_attackAttr2.clear();
+ _isShooting = false;
// TODO: clear everything
@@ -652,13 +653,15 @@ void Combat::checkParty() {
loop1();
}
-void Combat::attackMonster68() {
+void Combat::attackMonsterPhysical() {
_attackAttr1 = g_globals->_currCharacter->_physicalAttr;
+ _isShooting = false;
attackMonster(0);
}
-void Combat::attackMonster6a() {
+void Combat::attackMonsterShooting() {
_attackAttr1 = g_globals->_currCharacter->_missileAttr;
+ _isShooting = true;
attackMonster(0);
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 9b0cfecd0a8..3c0bd2b0aba 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -62,6 +62,8 @@ protected:
bool _monstersResistSpells;
bool _monstersRegenerate;
AttributePair _attackAttr1, _attackAttr2;
+ bool _isShooting;
+ Common::String _attackMessage;
enum Handicap {
HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
HANDICAP_MONSTER = 2
@@ -203,8 +205,8 @@ protected:
/**
* Attack a monster
*/
- void attackMonster68();
- void attackMonster6a();
+ void attackMonsterPhysical();
+ void attackMonsterShooting();
void attackMonster(int monsterNum);
};
Commit: e0b3883bcd5c911fd18d7933faf380039579b9cf
https://github.com/scummvm/scummvm/commit/e0b3883bcd5c911fd18d7933faf380039579b9cf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: Combat uses the party copy, not the main one
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index d2a1cd5362e..f2072117a39 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -62,6 +62,10 @@ void Combat::clear() {
// TODO: clear everything
_roundNum = 1;
+ _monstersCount = _monsterList.size();
+ _party.clear();
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ _party.push_back(&g_globals->_party[i]);
}
void Combat::loadArrays() {
@@ -102,7 +106,7 @@ void Combat::setupCanAttacks() {
if ((int8)map[Maps::MAP_ID] < 0) {
if (enc._encounterType != FORCE_SURPRISED) {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ for (uint i = 0; i < _party.size(); ++i) {
if (i < (MAX_PARTY_SIZE - 1)) {
_canAttack[i] = true;
} else {
@@ -117,17 +121,17 @@ void Combat::setupCanAttacks() {
} else {
if (enc._encounterType != FORCE_SURPRISED) {
_canAttack[0] = true;
- if (g_globals->_party.size() > 1)
+ if (_party.size() > 1)
_canAttack[1] = true;
- if (g_globals->_party.size() > 2)
+ if (_party.size() > 2)
checkLeftWall();
- if (g_globals->_party.size() > 3)
+ if (_party.size() > 3)
checkRightWall();
- if (g_globals->_party.size() > 4) {
+ if (_party.size() > 4) {
if (_canAttack[2] && getRandomNumber(100) <= 5)
_canAttack[4] = true;
}
- if (g_globals->_party.size() > 5) {
+ if (_party.size() > 5) {
if (_canAttack[3] && getRandomNumber(100) <= 5)
_canAttack[5] = true;
}
@@ -140,13 +144,13 @@ void Combat::setupCanAttacks() {
// Entire party is allowed to attack, I guess
// because the monsters are surrounding the party,
// placing them within reach
- Common::fill(&_canAttack[0], &_canAttack[g_globals->_party.size()], true);
+ Common::fill(&_canAttack[0], &_canAttack[_party.size()], true);
setupAttackerVal();
}
void Combat::setupAttackerVal() {
_attackerVal = 0;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ for (uint i = 0; i < _party.size(); ++i) {
if (_canAttack[i])
++_attackerVal;
}
@@ -206,8 +210,8 @@ void Combat::dispelParty() {
Character *tmpC = g_globals->_currCharacter;
Monster *tmpM = _monsterP;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
+ for (uint i = 0; i < _party.size(); ++i) {
+ Character &c = *_party[i];
g_globals->_currCharacter = &c;
c.updateAttributes();
c.updateAC();
@@ -236,8 +240,8 @@ void Combat::combatLoop() {
}
void Combat::selectParty() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
+ for (uint i = 0; i < _party.size(); ++i) {
+ Character &c = *_party[i];
g_globals->_currCharacter = &c;
int speed = c._speed._current;
@@ -267,16 +271,16 @@ void Combat::defeatedMonsters() {
}
// Count number of active characters
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- if (!(g_globals->_party[i]._condition & BAD_CONDITION))
+ for (uint i = 0; i < _party.size(); ++i) {
+ if (!(_party[i]->_condition & BAD_CONDITION))
++activeCharCount;
}
// Split the experience between the active characters
_totalExperience /= activeCharCount;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- if (!(g_globals->_party[i]._condition & BAD_CONDITION))
- g_globals->_party[i]._exp += _totalExperience;
+ for (uint i = 0; i < _party.size(); ++i) {
+ if (!(_party[i]->_condition & BAD_CONDITION))
+ _party[i]->_exp += _totalExperience;
}
// Update the party's characters
@@ -395,7 +399,7 @@ void Combat::nextRound() {
clearArrays();
g_globals->_party.updateAC();
- _val8 = getRandomNumber(g_globals->_party.size());
+ _val8 = getRandomNumber(_party.size());
updateHighestLevel();
setMode(NEXT_ROUND);
@@ -427,7 +431,7 @@ void Combat::clearArrays() {
void Combat::updateHighestLevel() {
Encounter &enc = g_globals->_encounters;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ for (uint i = 0; i < _party.size(); ++i) {
Character &c = g_globals->_party[i];
g_globals->_currCharacter = &c;
@@ -632,8 +636,8 @@ void Combat::checkParty() {
_val10 = 0;
bool partyAlive = false;
- for (auto &c : g_globals->_party) {
- if (!(c._condition & (DEAD | BAD_CONDITION)))
+ for (auto &c : _party) {
+ if (!(c->_condition & (DEAD | BAD_CONDITION)))
partyAlive = true;
}
@@ -644,8 +648,8 @@ void Combat::checkParty() {
}
// Update the array for the party
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
+ for (uint i = 0; i < _party.size(); ++i) {
+ Character &c = *_party[i];
if ((c._condition & BAD_CONDITION) || !c._hpBase)
_arr3[i] = 1;
}
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index c5c26553198..a266d9f7542 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -48,11 +48,6 @@ bool Combat::msgFocus(const FocusMessage &msg) {
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
- _monstersCount = _monsterList.size();
- _party.clear();
- for (uint i = 0; i < g_globals->_party.size(); ++i)
- _party.push_back(&g_globals->_party[i]);
-
loadArrays();
setupCanAttacks();
setupHandicap();
Commit: ace0ae5d1f97d73ef43810494a3a7ed4021cf4b2
https://github.com/scummvm/scummvm/commit/ace0ae5d1f97d73ef43810494a3a7ed4021cf4b2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:15+01:00
Commit Message:
MM: MM1: Further attack code
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 008b3959551..09e7169bbcc 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -315,6 +315,9 @@
regenerate: "SOME MONSTERS REGENERATE!"
overcome: "SOME MONSTERS OVERCOME SPELLS!"
monster_flees: "RUNS AWAY..."
+ attacks: "ATTACKS"
+ shoots: "SHOOTS"
+ weapon_no_effect: "WEAPON HAS NO EFFECT!"
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 7f15100f941..51f74585235 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -43,6 +43,10 @@ enum MonsterStatusFlag {
MONFLAG_PARALYZED = 0x80, MONFLAG_DEAD = 0xff
};
+enum Fiedl1A {
+ FIELD1A_80 = 0x80
+};
+
enum Field1E {
FIELD1E_10 = 0x10, FIELD1E_20 = 0x20,
FIELD1E_40 = 0x40, FIELD1E_80 = 0x80
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index f2072117a39..7e8618f6656 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -751,7 +751,57 @@ void Combat::attackMonster(int monsterNum) {
else
_attackAttr2._current = MAX((int)_attackAttr2._current - 3, 0);
- // TODO: attack message and further stuff
+ _message.clear();
+ _message.push_back(Line(0, 0, Common::String::format("%s %s %s",
+ g_globals->_currCharacter->_name,
+ STRING[_isShooting ? "dialogs.combat.shoots" :
+ "dialogs.combat.attacks"].c_str(),
+ _monsterP->_name.c_str()
+ )));
+
+ if (_isShooting && c._class == ARCHER)
+ _attackAttr2._current += (c._level + 1) / 2;
+ _isShooting = false;
+
+ if (_attackAttr1._current || !(_monsterP->_field1a & FIELD1A_80)) {
+ if (_monsterStatus[_monsterIndex] & (MONFLAG_ASLEEP |
+ MONFLAG_HELD | MONFLAG_WEBBED | MONFLAG_PARALYZED))
+ ++_attackerLevel;
+
+ if (g_globals->_spells._s.bless) {
+ _attackerLevel++;
+ _attackAttr2._current++;
+ }
+
+ if (g_globals->_spells._s.cursed) {
+ if (++_val11 > 255)
+ _val11 = 200;
+ }
+
+ writeAttackDamage();
+ if (_damage)
+ updateMonsterStatus();
+ } else {
+ _message.push_back(Line(0, 1, STRING["dialogs.combat.weapon_no_effect"]));
+ }
+
+ _arr3[_currentChar] = 1;
+ setMode(CHAR_ATTACKS);
+}
+
+void Combat::writeAttackDamage() {
+ // TODO: Implement
+}
+
+void Combat::updateMonsterStatus() {
+ int val = _arr1[_monsterIndex] - _damage;
+ if (val <= 0) {
+ _arr1[_monsterIndex] = 0;
+ _monsterStatus[_monsterIndex] = MONFLAG_DEAD;
+ } else {
+ _arr1[_monsterIndex] = val;
+ _monsterStatus[_monsterIndex] &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
+ }
}
} // namespace Game
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3c0bd2b0aba..1d35db8e868 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -36,6 +36,7 @@ namespace Game {
class Combat : public SpellsMonsters {
protected:
Common::Array<Monster> &_monsterList;
+ Common::Array<Line> _message;
int _monstersCount = 0;
Common::Array<Character *> _party;
Monster *_monsterP;
@@ -72,7 +73,8 @@ protected:
enum Mode {
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
- MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL
+ MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL,
+ CHAR_ATTACKS
};
Mode _mode = SELECT_OPTION;
@@ -208,6 +210,16 @@ protected:
void attackMonsterPhysical();
void attackMonsterShooting();
void attackMonster(int monsterNum);
+
+ /**
+ * Adds attack damage message for character hitting monster
+ */
+ void writeAttackDamage();
+
+ /**
+ * Updates a monster's status
+ */
+ void updateMonsterStatus();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index ef7de69fc4b..9065d09306c 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -46,7 +46,6 @@ private:
int _mmVal5 = 0;
int _mmVal7 = 0;
Resistance _resistanceType = RESISTANCE_MAGIC;
- int _damage = 0;
void spell01_curse();
void spell02_energyBlast();
@@ -184,6 +183,7 @@ private:
protected:
byte _arr1[MAX_COMBAT_MONSTERS];
byte _monsterStatus[MAX_COMBAT_MONSTERS];
+ int _damage = 0;
virtual bool canMonsterCast() const = 0;
virtual int getMonsterIndex() const = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index a266d9f7542..fa43aab8f94 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -90,6 +90,11 @@ void Combat::draw() {
writeMonsterSpell();
delaySeconds(2);
return;
+ case CHAR_ATTACKS:
+ writeMonsters();
+ writeMessage();
+ delaySeconds(3);
+ return;
default:
break;
}
@@ -127,6 +132,7 @@ void Combat::timeout() {
nextRound3();
return;
case MONSTERS_AFFECTED:
+ case CHAR_ATTACKS:
combatLoop();
return;
case MONSTER_FLEES:
@@ -194,6 +200,8 @@ bool Combat::msgAction(const ActionMessage &msg) {
default:
break;
}
+
+ return true;
}
void Combat::writeOptions() {
@@ -438,7 +446,7 @@ void Combat::writeMonsterAction() {
void Combat::writeMonsterSpell() {
resetBottom();
- for (uint i = 0, y = 0; i < _monsterSpellLines.size() &&
+ for (int i = 0, y = 0; i < (int)_monsterSpellLines.size() &&
_monsterSpellLines[i].y > y;
y = _monsterSpellLines[i].y, ++i) {
Common::String text = _monsterSpellLines[i]._text;
@@ -493,6 +501,19 @@ void Combat::shoot() {
void Combat::use() {
}
+void Combat::writeMessage() {
+ size_t idx;
+
+ resetBottom();
+ for (const auto &line : _message) {
+ Common::String text = line._text;
+ while ((idx = text.findFirstOf('|')) != Common::String::npos)
+ text.deleteChar(idx);
+
+ writeString(line.x, line.y, text);
+ }
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 7cbec5d50a3..59db293c589 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -158,6 +158,11 @@ private:
*/
void use();
+ /**
+ * Writes out a message
+ */
+ void writeMessage();
+
protected:
/**
* Sets a new display mode
Commit: bb1a1af1e0e4b0c15748b47283c87ef50298acf0
https://github.com/scummvm/scummvm/commit/bb1a1af1e0e4b0c15748b47283c87ef50298acf0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: Remainder of character attack calculation and display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 09e7169bbcc..47ad9470116 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -318,6 +318,16 @@
attacks: "ATTACKS"
shoots: "SHOOTS"
weapon_no_effect: "WEAPON HAS NO EFFECT!"
+ once: "ONCE"
+ times: "TIMES"
+ and: "AND"
+ hit: "HIT"
+ misses: "MISSES"
+ for: "FOR"
+ point: "POINT"
+ points: "POINTS"
+ of_damage: "OF DAMAGE!"
+
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 7e8618f6656..719008c8586 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -43,7 +43,7 @@ void Combat::clear() {
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_val6 = _val7 = 0;
_val8 = _val9 = _val10 = 0;
- _val11 = _val12 = 0;
+ _val11 = _numberOfTimes = 0;
_attackerLevel = 0;
_advanceIndex = 0;
_handicap1 = _handicap2 = 0;
@@ -57,6 +57,7 @@ void Combat::clear() {
_monstersResistSpells = _monstersRegenerate = false;
_attackAttr1.clear();
_attackAttr2.clear();
+ _timesHit = 0;
_isShooting = false;
// TODO: clear everything
@@ -707,10 +708,10 @@ void Combat::attackMonster(int monsterNum) {
else
_attackerLevel = MAX((int)_attackerLevel - 3, 0);
- _val12 = 1;
+ _numberOfTimes = 1;
if (c._class >= CLERIC && c._level >= 8) {
- _val12 += c._level / 8;
+ _numberOfTimes += c._level / 8;
}
// Affect level based on might
@@ -751,17 +752,8 @@ void Combat::attackMonster(int monsterNum) {
else
_attackAttr2._current = MAX((int)_attackAttr2._current - 3, 0);
- _message.clear();
- _message.push_back(Line(0, 0, Common::String::format("%s %s %s",
- g_globals->_currCharacter->_name,
- STRING[_isShooting ? "dialogs.combat.shoots" :
- "dialogs.combat.attacks"].c_str(),
- _monsterP->_name.c_str()
- )));
-
if (_isShooting && c._class == ARCHER)
_attackAttr2._current += (c._level + 1) / 2;
- _isShooting = false;
if (_attackAttr1._current || !(_monsterP->_field1a & FIELD1A_80)) {
if (_monsterStatus[_monsterIndex] & (MONFLAG_ASLEEP |
@@ -778,7 +770,7 @@ void Combat::attackMonster(int monsterNum) {
_val11 = 200;
}
- writeAttackDamage();
+ addAttackDamage();
if (_damage)
updateMonsterStatus();
} else {
@@ -789,8 +781,19 @@ void Combat::attackMonster(int monsterNum) {
setMode(CHAR_ATTACKS);
}
-void Combat::writeAttackDamage() {
- // TODO: Implement
+void Combat::addAttackDamage() {
+ _damage = 0;
+ _timesHit = 0;
+ _val11 += 10;
+
+ for (int i = 0; i < _numberOfTimes; ++i) {
+ int val = getRandomNumber(20);
+ if (val == 20 || (val != 1 && (val + _attackerLevel) >= _val11)) {
+ _damage = MAX(_damage + (int)_attackAttr2._current +
+ getRandomNumber(_attackAttr2._base), 255);
+ ++_timesHit;
+ }
+ }
}
void Combat::updateMonsterStatus() {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 1d35db8e868..46e35d641fb 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -52,7 +52,7 @@ protected:
char _val2, _val3, _val4, _val5;
byte _val6, _val7;
int _val8, _val9, _val10;
- int _val11, _val12;
+ int _val11, _numberOfTimes;
int _attackerLevel;
int _advanceIndex;
int _handicap1, _handicap2;
@@ -63,6 +63,7 @@ protected:
bool _monstersResistSpells;
bool _monstersRegenerate;
AttributePair _attackAttr1, _attackAttr2;
+ int _timesHit;
bool _isShooting;
Common::String _attackMessage;
enum Handicap {
@@ -214,7 +215,7 @@ protected:
/**
* Adds attack damage message for character hitting monster
*/
- void writeAttackDamage();
+ void addAttackDamage();
/**
* Updates a monster's status
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index fa43aab8f94..69dbed8a72e 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -92,7 +92,7 @@ void Combat::draw() {
return;
case CHAR_ATTACKS:
writeMonsters();
- writeMessage();
+ writeCharAttackDamage();
delaySeconds(3);
return;
default:
@@ -514,6 +514,55 @@ void Combat::writeMessage() {
}
}
+void Combat::writeCharAttackDamage() {
+ writeString(0, 0, Common::String::format("%s %s %s",
+ g_globals->_currCharacter->_name,
+ STRING[_isShooting ? "dialogs.combat.shoots" :
+ "dialogs.combat.attacks"].c_str(),
+ _monsterP->_name.c_str()
+ ));
+ _isShooting = false;
+
+ Common::String line1;
+ if (_numberOfTimes == 1) {
+ line1 = STRING["dialogs.combat.once"];
+ } else {
+ line1 = Common::String::format("%d %s", _numberOfTimes,
+ STRING["dialogs.combat.times"].c_str());
+ }
+
+ line1 += Common::String::format(" %s ", STRING["dialogs.combat.and"].c_str());
+
+ if (_damage == 0) {
+ line1 += STRING["dialogs.combat.misses"];
+ } else {
+ line1 += STRING["dialogs.combat.hit"];
+ line1 += ' ';
+
+ if (_numberOfTimes > 1) {
+ if (_timesHit == 1) {
+ line1 += STRING["dialogs.combat.once"];
+ } else {
+ line1 += Common::String::format("%d %s", _timesHit,
+ STRING["dialogs.combat.times"].c_str());
+ }
+ }
+
+ line1 += Common::String::format(" %s %d %s",
+ STRING["dialogs.combat.for"].c_str(), _damage,
+ STRING[_damage == 1 ? "dialogs.combat.point" : "dialogs.combat.points"].c_str());
+
+ if (line1.size() < 30) {
+ line1 += ' ';
+ line1 += STRING["dialogs.combat.of_damage"];
+ } else {
+ line1 += '!';
+ }
+ }
+
+ writeString(0, 1, line1);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 59db293c589..0fca22b0f01 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -158,6 +158,11 @@ private:
*/
void use();
+ /**
+ * Write message for characters attacking monsters
+ */
+ void writeCharAttackDamage();
+
/**
* Writes out a message
*/
Commit: 58d2f1555356c489af78e52bf95537cb43be3fe9
https://github.com/scummvm/scummvm/commit/58d2f1555356c489af78e52bf95537cb43be3fe9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: Added fight and shoot combat options
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 47ad9470116..651a62de8d5 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -327,7 +327,8 @@
point: "POINT"
points: "POINTS"
of_damage: "OF DAMAGE!"
-
+ fight_which: "FIGHT WHICH 'A'-'%d'?"
+ shoot_which: "SHOOT WHICH 'A'-'%d'?"
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 719008c8586..69deec04731 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -43,7 +43,8 @@ void Combat::clear() {
_val1 = _val2 = _val3 = _val4 = _val5 = 0;
_val6 = _val7 = 0;
_val8 = _val9 = _val10 = 0;
- _val11 = _numberOfTimes = 0;
+ _val11 = 0;
+ _numberOfTimes = 0;
_attackerLevel = 0;
_advanceIndex = 0;
_handicap1 = _handicap2 = 0;
@@ -658,6 +659,18 @@ void Combat::checkParty() {
loop1();
}
+void Combat::fightMonster(int monsterNum) {
+ _attackAttr1 = g_globals->_currCharacter->_physicalAttr;
+ _isShooting = false;
+ attackMonster(monsterNum);
+}
+
+void Combat::shootMonster(int monsterNum) {
+ _attackAttr1 = g_globals->_currCharacter->_missileAttr;
+ _isShooting = true;
+ attackMonster(monsterNum);
+}
+
void Combat::attackMonsterPhysical() {
_attackAttr1 = g_globals->_currCharacter->_physicalAttr;
_isShooting = false;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 46e35d641fb..325e36fd9bf 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -208,6 +208,8 @@ protected:
/**
* Attack a monster
*/
+ void fightMonster(int monsterNum);
+ void shootMonster(int monsterNum);
void attackMonsterPhysical();
void attackMonsterShooting();
void attackMonster(int monsterNum);
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 69dbed8a72e..5509742d178 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -35,6 +35,13 @@ Combat::Combat() : TextView("Combat") {
void Combat::setMode(Mode newMode) {
_mode = newMode;
+ if (newMode == SELECT_OPTION) {
+ _option = OPTION_NONE;
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
+ } else {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ }
+
if (_mode == MONSTER_SPELL)
// Make a copy of monster spell
_monsterSpellLines = getMonsterSpellMessage();
@@ -165,6 +172,18 @@ void Combat::timeout() {
}
bool Combat::msgKeypress(const KeypressMessage &msg) {
+ if (_mode == SELECT_OPTION && _option != OPTION_NONE) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ combatLoop();
+ } else if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode < (int)(Common::KEYCODE_a + _fightCount)) {
+ if (_option == OPTION_FIGHT)
+ fightMonster(msg.keycode - Common::KEYCODE_a);
+ else
+ shootMonster(msg.keycode - Common::KEYCODE_a);
+ }
+ }
+
return true;
}
@@ -211,6 +230,12 @@ void Combat::writeOptions() {
case OPTION_NONE:
writeAllOptions();
break;
+ case OPTION_FIGHT:
+ writeFightSelect();
+ break;
+ case OPTION_SHOOT:
+ writeShootSelect();
+ break;
default:
break;
}
@@ -266,6 +291,22 @@ void Combat::writeAllOptions() {
writeString(16, 23, STRING["dialogs.combat.retreat_block"]);
}
+void Combat::writeFightSelect() {
+ _fightCount = MIN(_attackerVal, (int)_monsterList.size());
+
+ writeString(10, 0, Common::String::format(
+ STRING["dialogs.combat.fight_which"].c_str(), '@' + _fightCount));
+ escToGoBack(12, 3);
+}
+
+void Combat::writeShootSelect() {
+ _fightCount = MIN(_attackerVal, (int)_monsterList.size());
+
+ writeString(10, 0, Common::String::format(
+ STRING["dialogs.combat.shoot_which"].c_str(), '@' + _fightCount));
+ escToGoBack(12, 3);
+}
+
void Combat::writeAttackOptions() {
writeString(16, 20, STRING["dialogs.combat.attack"]);
writeString(16, 21, STRING["dialogs.combat.fight"]);
@@ -474,10 +515,8 @@ void Combat::checkMonsterSpellDone() {
}
void Combat::attack() {
- if (_val5 == 32)
- return;
-
- attackMonster(0);
+ if (_val5 != 32)
+ attackMonsterPhysical();
}
void Combat::block() {
@@ -490,12 +529,26 @@ void Combat::exchange() {
}
void Combat::fight() {
+ if (_val2 != 32) {
+ if (_monsterList.size() < 2) {
+ attackMonsterPhysical();
+ } else {
+ setOption(OPTION_FIGHT);
+ }
+ }
}
void Combat::retreat() {
}
void Combat::shoot() {
+ if (_val3 != 32) {
+ if (_monsterList.size() < 2) {
+ attackMonsterPhysical();
+ } else {
+ setOption(OPTION_SHOOT);
+ }
+ }
}
void Combat::use() {
@@ -563,6 +616,11 @@ void Combat::writeCharAttackDamage() {
writeString(0, 1, line1);
}
+void Combat::setOption(SelectedOption option) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ _option = option;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 0fca22b0f01..53c631439a9 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -32,12 +32,18 @@ namespace Views {
class Combat : public TextView, public Game::Combat {
private:
LineArray _monsterSpellLines;
+ uint _fightCount = 0;
// Combat options that have sub-option selection
enum SelectedOption {
- OPTION_NONE, OPTION_ATTACK
+ OPTION_NONE, OPTION_FIGHT, OPTION_SHOOT
};
SelectedOption _option = OPTION_NONE;
+ /**
+ * Selects a combat option that requires a selection
+ */
+ void setOption(SelectedOption option);
+
void writeOptions();
void writeAllOptions();
void writeAttackOptions();
@@ -168,6 +174,16 @@ private:
*/
void writeMessage();
+ /**
+ * Having selected to fight, selects monster to attack
+ */
+ void writeFightSelect();
+
+ /**
+ * Having selected to shoot, selects monster to attack
+ */
+ void writeShootSelect();
+
protected:
/**
* Sets a new display mode
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index f3e7fa42882..7882a7b9532 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -128,9 +128,11 @@ void TextView::drawTextBorder() {
}
}
-void TextView::escToGoBack(int x) {
- writeString(x, (_bounds.height() / FONT_SIZE) - 1,
- STRING["dialogs.misc.go_back"]);
+void TextView::escToGoBack(int x, int y) {
+ if (y == -1)
+ y = (_bounds.height() / FONT_SIZE) - 1;
+
+ writeString(x, y, STRING["dialogs.misc.go_back"]);
}
void TextView::timeout() {
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index cd6f4487abf..4374bc81a0c 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -90,7 +90,7 @@ protected:
/**
* Prints a message 'ESC' to go back
*/
- void escToGoBack(int x = 12);
+ void escToGoBack(int x = 12, int y = -1);
/**
* Called when an active timeout countdown expired
Commit: c7e9551cb1c2cbc2acce91c86d79b1f5fa531fcc
https://github.com/scummvm/scummvm/commit/c7e9551cb1c2cbc2acce91c86d79b1f5fa531fcc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: Added delay setting
Though actual use of resulting delay isn't used yet
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/globals.h
engines/mm/mm1/meta_engine.cpp
engines/mm/mm1/meta_engine.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 651a62de8d5..f35a1aa253f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -329,6 +329,8 @@
of_damage: "OF DAMAGE!"
fight_which: "FIGHT WHICH 'A'-'%d'?"
shoot_which: "SHOOT WHICH 'A'-'%d'?"
+ set_delay: "SET DELAY (0-9):"
+ delay_currently: "(CURRENTLY= %d)"
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index ee1f3233474..acebf3a004a 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -51,6 +51,7 @@ public:
Game::Encounter _encounters;
Monsters _monsters;
byte _treasure[TREASURE_COUNT];
+ byte _delay = 5;
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index fd675e78d45..5fe6738c8cf 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -52,14 +52,17 @@ static const KeybindingRecord PARTY_KEYS[] = {
};
static const KeybindingRecord COMBAT_KEYS[] = {
- { KEYBIND_COMBAT_ATTACK, "COMBAT_ATTACK", "Attack", "A", nullptr },
- { KEYBIND_COMBAT_BLOCK, "COMBAT_BLOCK", "Block", "B", nullptr },
- { KEYBIND_COMBAT_CAST, "COMBAT_CAST", "Cast", "C", nullptr },
- { KEYBIND_COMBAT_EXCHANGE, "COMBAT_EXCHANGE", "Exchange", "E", nullptr },
- { KEYBIND_COMBAT_FIGHT, "COMBAT_FIGHT", "Fight", "F", nullptr },
- { KEYBIND_COMBAT_RETREAT, "COMBAT_RETREAT", "Retreat", "R", nullptr },
- { KEYBIND_COMBAT_SHOOT, "COMBAT_SHOOT", "Shoot", "S", nullptr },
- { KEYBIND_COMBAT_USE, "COMBAT_USE", "Use", "U", nullptr },
+ { KEYBIND_COMBAT_ATTACK, "COMBAT_ATTACK", "Attack", "a", nullptr },
+ { KEYBIND_COMBAT_BLOCK, "COMBAT_BLOCK", "Block", "b", nullptr },
+ { KEYBIND_COMBAT_CAST, "COMBAT_CAST", "Cast", "c", nullptr },
+ { KEYBIND_QUICKREF, "DELAY", "Delay", "d", nullptr },
+ { KEYBIND_COMBAT_EXCHANGE, "COMBAT_EXCHANGE", "Exchange", "e", nullptr },
+ { KEYBIND_COMBAT_FIGHT, "COMBAT_FIGHT", "Fight", "f", nullptr },
+ { KEYBIND_QUICKREF, "PROTECT", "Protect", "p", nullptr },
+ { KEYBIND_QUICKREF, "QUICKREF", "Quick Reference", "q", nullptr },
+ { KEYBIND_COMBAT_RETREAT, "COMBAT_RETREAT", "Retreat", "r", nullptr },
+ { KEYBIND_COMBAT_SHOOT, "COMBAT_SHOOT", "Shoot", "s", nullptr },
+ { KEYBIND_COMBAT_USE, "COMBAT_USE", "Use", "u", nullptr },
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
};
diff --git a/engines/mm/mm1/meta_engine.h b/engines/mm/mm1/meta_engine.h
index c336b201013..50853da3fd7 100644
--- a/engines/mm/mm1/meta_engine.h
+++ b/engines/mm/mm1/meta_engine.h
@@ -64,8 +64,10 @@ enum KeybindingAction {
KEYBIND_COMBAT_ATTACK,
KEYBIND_COMBAT_BLOCK,
KEYBIND_COMBAT_CAST,
+ KEYBIND_COMBAT_DELAY,
KEYBIND_COMBAT_EXCHANGE,
KEYBIND_COMBAT_FIGHT,
+ KEYBIND_COMBAT_PROTECT,
KEYBIND_COMBAT_RETREAT,
KEYBIND_COMBAT_SHOOT,
KEYBIND_COMBAT_USE,
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 5509742d178..27e239ee29e 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -175,12 +175,31 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
if (_mode == SELECT_OPTION && _option != OPTION_NONE) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
combatLoop();
- } else if (msg.keycode >= Common::KEYCODE_a &&
+ return true;
+ }
+
+ switch (_option) {
+ case OPTION_FIGHT:
+ case OPTION_SHOOT:
+ if (msg.keycode >= Common::KEYCODE_a &&
msg.keycode < (int)(Common::KEYCODE_a + _fightCount)) {
- if (_option == OPTION_FIGHT)
- fightMonster(msg.keycode - Common::KEYCODE_a);
- else
- shootMonster(msg.keycode - Common::KEYCODE_a);
+ if (_option == OPTION_FIGHT)
+ fightMonster(msg.keycode - Common::KEYCODE_a);
+ else
+ shootMonster(msg.keycode - Common::KEYCODE_a);
+ }
+ break;
+
+ case OPTION_DELAY:
+ if (msg.keycode >= Common::KEYCODE_0 &&
+ msg.keycode <= Common::KEYCODE_9) {
+ g_globals->_delay = msg.keycode - Common::KEYCODE_0;
+ combatLoop();
+ }
+ break;
+
+ default:
+ break;
}
}
@@ -201,12 +220,18 @@ bool Combat::msgAction(const ActionMessage &msg) {
case KEYBIND_COMBAT_CAST:
cast();
break;
+ case KEYBIND_COMBAT_DELAY:
+ delay();
+ break;
case KEYBIND_COMBAT_EXCHANGE:
exchange();
break;
case KEYBIND_COMBAT_FIGHT:
fight();
break;
+ case KEYBIND_COMBAT_PROTECT:
+ protect();
+ break;
case KEYBIND_COMBAT_RETREAT:
retreat();
break;
@@ -217,6 +242,7 @@ bool Combat::msgAction(const ActionMessage &msg) {
use();
break;
default:
+ // TODO: Character and quickref views
break;
}
@@ -230,6 +256,9 @@ void Combat::writeOptions() {
case OPTION_NONE:
writeAllOptions();
break;
+ case OPTION_DELAY:
+ writeDelaySelect();
+ break;
case OPTION_FIGHT:
writeFightSelect();
break;
@@ -291,6 +320,15 @@ void Combat::writeAllOptions() {
writeString(16, 23, STRING["dialogs.combat.retreat_block"]);
}
+void Combat::writeDelaySelect() {
+ resetBottom();
+ writeString(0, 0, STRING["dialogs.combat.set_delay"]);
+ writeString(0, 26, Common::String::format(
+ STRING["dialogs.combat.delay_currently"].c_str(),
+ g_globals->_delay));
+ escToGoBack(0, 3);
+}
+
void Combat::writeFightSelect() {
_fightCount = MIN(_attackerVal, (int)_monsterList.size());
@@ -525,6 +563,10 @@ void Combat::block() {
void Combat::cast() {
}
+void Combat::delay() {
+ setOption(OPTION_DELAY);
+}
+
void Combat::exchange() {
}
@@ -538,6 +580,9 @@ void Combat::fight() {
}
}
+void Combat::protect() {
+}
+
void Combat::retreat() {
}
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 53c631439a9..e247e53b2f2 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -35,7 +35,8 @@ private:
uint _fightCount = 0;
// Combat options that have sub-option selection
enum SelectedOption {
- OPTION_NONE, OPTION_FIGHT, OPTION_SHOOT
+ OPTION_NONE, OPTION_DELAY, OPTION_FIGHT,
+ OPTION_SHOOT
};
SelectedOption _option = OPTION_NONE;
@@ -139,6 +140,11 @@ private:
*/
void cast();
+ /**
+ * Delay option
+ */
+ void delay();
+
/**
* Exchange option
*/
@@ -149,6 +155,11 @@ private:
*/
void fight();
+ /**
+ * Protect option
+ */
+ void protect();
+
/**
* Retreat option
*/
@@ -174,6 +185,11 @@ private:
*/
void writeMessage();
+ /**
+ * Writes text for delay number selection
+ */
+ void writeDelaySelect();
+
/**
* Having selected to fight, selects monster to attack
*/
Commit: fc5a8714f7a3f4143f0c513728925285835a23f1
https://github.com/scummvm/scummvm/commit/fc5a8714f7a3f4143f0c513728925285835a23f1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: Added Protect and QuickRef display from combat
Changed paths:
engines/mm/mm1/meta_engine.cpp
engines/mm/mm1/meta_engine.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
engines/mm/mm1/views/game.cpp
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index 5fe6738c8cf..da7f69839cd 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -55,14 +55,15 @@ static const KeybindingRecord COMBAT_KEYS[] = {
{ KEYBIND_COMBAT_ATTACK, "COMBAT_ATTACK", "Attack", "a", nullptr },
{ KEYBIND_COMBAT_BLOCK, "COMBAT_BLOCK", "Block", "b", nullptr },
{ KEYBIND_COMBAT_CAST, "COMBAT_CAST", "Cast", "c", nullptr },
- { KEYBIND_QUICKREF, "DELAY", "Delay", "d", nullptr },
{ KEYBIND_COMBAT_EXCHANGE, "COMBAT_EXCHANGE", "Exchange", "e", nullptr },
{ KEYBIND_COMBAT_FIGHT, "COMBAT_FIGHT", "Fight", "f", nullptr },
- { KEYBIND_QUICKREF, "PROTECT", "Protect", "p", nullptr },
{ KEYBIND_QUICKREF, "QUICKREF", "Quick Reference", "q", nullptr },
{ KEYBIND_COMBAT_RETREAT, "COMBAT_RETREAT", "Retreat", "r", nullptr },
{ KEYBIND_COMBAT_SHOOT, "COMBAT_SHOOT", "Shoot", "s", nullptr },
{ KEYBIND_COMBAT_USE, "COMBAT_USE", "Use", "u", nullptr },
+
+ { KEYBIND_DELAY, "DELAY", "Delay", "d", nullptr },
+ { KEYBIND_PROTECT, "PROTECT", "Protect", "p", nullptr },
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
};
diff --git a/engines/mm/mm1/meta_engine.h b/engines/mm/mm1/meta_engine.h
index 50853da3fd7..c23c78f8cd0 100644
--- a/engines/mm/mm1/meta_engine.h
+++ b/engines/mm/mm1/meta_engine.h
@@ -36,6 +36,7 @@ enum KeybindingAction {
KEYBIND_TURN_RIGHT,
KEYBIND_STRAFE_LEFT,
KEYBIND_STRAFE_RIGHT,
+ KEYBIND_DELAY,
KEYBIND_MAP,
KEYBIND_ORDER,
KEYBIND_PROTECT,
@@ -64,10 +65,8 @@ enum KeybindingAction {
KEYBIND_COMBAT_ATTACK,
KEYBIND_COMBAT_BLOCK,
KEYBIND_COMBAT_CAST,
- KEYBIND_COMBAT_DELAY,
KEYBIND_COMBAT_EXCHANGE,
KEYBIND_COMBAT_FIGHT,
- KEYBIND_COMBAT_PROTECT,
KEYBIND_COMBAT_RETREAT,
KEYBIND_COMBAT_SHOOT,
KEYBIND_COMBAT_USE,
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 27e239ee29e..4dc46e5e417 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -220,7 +220,7 @@ bool Combat::msgAction(const ActionMessage &msg) {
case KEYBIND_COMBAT_CAST:
cast();
break;
- case KEYBIND_COMBAT_DELAY:
+ case KEYBIND_DELAY:
delay();
break;
case KEYBIND_COMBAT_EXCHANGE:
@@ -229,8 +229,11 @@ bool Combat::msgAction(const ActionMessage &msg) {
case KEYBIND_COMBAT_FIGHT:
fight();
break;
- case KEYBIND_COMBAT_PROTECT:
- protect();
+ case KEYBIND_PROTECT:
+ addView("Protect");
+ break;
+ case KEYBIND_QUICKREF:
+ addView("QuickRef");
break;
case KEYBIND_COMBAT_RETREAT:
retreat();
@@ -580,9 +583,6 @@ void Combat::fight() {
}
}
-void Combat::protect() {
-}
-
void Combat::retreat() {
}
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index e247e53b2f2..6fa07d5b32e 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -155,11 +155,6 @@ private:
*/
void fight();
- /**
- * Protect option
- */
- void protect();
-
/**
* Retreat option
*/
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 391055eeb5e..b41b4214e96 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -53,6 +53,9 @@ bool Game::msgAction(const ActionMessage &msg) {
// g_events->send("Game", GameMessage("ORDER"));
addView("Order");
return true;
+ case KEYBIND_PROTECT:
+ addView("Protect");
+ return true;
case KEYBIND_QUICKREF:
addView("QuickRef");
return true;
Commit: 9ec569d286074834c0f81518f4dceaa6a2546d49
https://github.com/scummvm/scummvm/commit/9ec569d286074834c0f81518f4dceaa6a2546d49
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: In progress implementing character info use action
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/mm1/views/combat.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index f35a1aa253f..abf391af87e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -43,6 +43,7 @@
gather_all: "GATHER ALL:"
trade_with: "TRADE WITH: '1'-'%d'"
trade_which: "TRADE WHICH:"
+ use_what: "USE WHICH 'A'-'F','1'-'6'?"
gems: "1) GEMS"
gold: "2) GOLD"
food: "3) FOOD"
@@ -50,6 +51,9 @@
how_much: "HOW MUCH:"
cast_spell: "CAST SPELL: LEVEL="
number: "NUMBER="
+ use_no_special_power: "NO SPECIAL POWER"
+ use_not_equipped: "NOT EQUIPPED"
+ no_charges_left: "NO CHARGES LEFT"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index ab5753e529c..7f99055bdab 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -55,7 +55,7 @@ struct ItemData {
byte _disablements;
EquipMode _equipMode;
byte _val10;
- byte _val11;
+ byte _effectId;
byte _spellId;
byte _maxCharges;
uint16 _cost;
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 8b11da6ee76..c26e88d23c6 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -92,6 +92,11 @@ void CharacterInfo::draw() {
escToGoBack(0);
break;
+ case USE:
+ writeString(7, 20, STRING["dialogs.character.use_what"]);
+ escToGoBack(0);
+ break;
+
default:
break;
}
@@ -140,6 +145,10 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
_state = TRADE_WITH;
redraw();
break;
+ case Common::KEYCODE_u:
+ _state = USE;
+ redraw();
+ break;
default:
break;
}
@@ -207,6 +216,38 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
}
break;
+ case USE: {
+ Character &c = *g_globals->_currCharacter;
+ const Inventory::Entry *invEntry;
+ Item *item;
+ if (msg.keycode >= Common::KEYCODE_1 && msg.keycode <= Common::KEYCODE_6 &&
+ (msg.keycode - Common::KEYCODE_1) < (int)c._equipped.size()) {
+ invEntry = &c._equipped[msg.keycode - Common::KEYCODE_1];
+ } else if (msg.keycode >= Common::KEYCODE_a && msg.keycode <= Common::KEYCODE_f &&
+ (msg.keycode - Common::KEYCODE_a) < (int)c._backpack.size()) {
+ invEntry = &c._backpack[msg.keycode - Common::KEYCODE_a];
+ } else {
+ break;
+ }
+
+ item = getItem(invEntry->_id);
+
+ clearLines(20, 24);
+ if (!item->_effectId) {
+ writeString(8, 21, STRING["dialogs.character.no_special_power"]);
+ delaySeconds(3);
+ } else if (item->_equipMode == NOT_EQUIPPABLE ||
+ msg.keycode >= Common::KEYCODE_a) {
+ if (invEntry->_charges) {
+ // TODO: Handle charges
+
+ } else {
+ writeString(8, 21, STRING["dialogs.character.no_charges_left"]);
+ delaySeconds(3);
+ }
+ }
+ break;
+ }
default:
break;
}
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 4fa9ef321b8..7ed2fffad1f 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -38,7 +38,7 @@ class CharacterInfo : public CharacterBase {
private:
enum ViewState {
DISPLAY, EQUIP, GATHER, REMOVE, SHARE,
- TRADE_WITH, TRADE_KIND, TRADE_ITEM };
+ TRADE_WITH, TRADE_KIND, TRADE_ITEM, USE };
ViewState _state = DISPLAY;
Common::String _newName;
private:
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 4dc46e5e417..2061bdab9fd 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -363,7 +363,7 @@ void Combat::writeShootOption() {
void Combat::resetBottom() {
clearLines(20, 24);
- _val2 = _val3 = _val4 = _val5 = ' ';
+ _val2 = _val3 = _val4 = _val5 = 32;
}
void Combat::writeStaticContent() {
Commit: db2e6e15f9fb1c6cd24d08d466adea816f026048
https://github.com/scummvm/scummvm/commit/db2e6e15f9fb1c6cd24d08d466adea816f026048
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: Clarified flags for allowing combat actions
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index cb76835436c..9c8490a323c 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -298,6 +298,14 @@ public:
return _views.empty() ? nullptr : _views.top();
}
+ /**
+ * Returns the view prior to the current view, if any
+ */
+ UIElement *priorView() const {
+ return _views.size() < 2 ? nullptr :
+ _views[_views.size() - 2];
+ }
+
Graphics::Screen *getScreen() const {
return _screen;
}
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 69deec04731..3452ebde676 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -40,7 +40,8 @@ void Combat::clear() {
Common::fill(&_canAttack[0], &_canAttack[6], false);
Common::fill(&_treasureFlags[0], &_treasureFlags[MAX_PARTY_SIZE], false);
- _val1 = _val2 = _val3 = _val4 = _val5 = 0;
+ _allowFight = _allowShoot = _allowCast = _allowAttack = false;
+ _val1 = 0;
_val6 = _val7 = 0;
_val8 = _val9 = _val10 = 0;
_val11 = 0;
@@ -382,9 +383,9 @@ void Combat::selectTreasure2(int count) {
val2 = TREASURES_ARR2[idx];
for (idx = 0; idx < count; ++idx)
- _val1 += _val2;
+ _val1 += _allowFight;
- _val1 += getRandomNumber(_val2) - 1;
+ _val1 += getRandomNumber(_allowFight) - 1;
auto &treasure = g_globals->_treasure;
if (!treasure[2])
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 325e36fd9bf..401e086c4ca 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -49,7 +49,7 @@ protected:
int _val1;
int _roundNum;
int _monsterIndex, _currentChar;
- char _val2, _val3, _val4, _val5;
+ bool _allowFight, _allowShoot, _allowCast, _allowAttack;
byte _val6, _val7;
int _val8, _val9, _val10;
int _val11, _numberOfTimes;
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index c26e88d23c6..34486bf992b 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views/character_info.h"
+#include "mm/mm1/views/combat.h"
#include "mm/mm1/utils/strings.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
@@ -218,8 +219,7 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case USE: {
Character &c = *g_globals->_currCharacter;
- const Inventory::Entry *invEntry;
- Item *item;
+ Inventory::Entry *invEntry;
if (msg.keycode >= Common::KEYCODE_1 && msg.keycode <= Common::KEYCODE_6 &&
(msg.keycode - Common::KEYCODE_1) < (int)c._equipped.size()) {
invEntry = &c._equipped[msg.keycode - Common::KEYCODE_1];
@@ -230,22 +230,10 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
break;
}
- item = getItem(invEntry->_id);
-
- clearLines(20, 24);
- if (!item->_effectId) {
- writeString(8, 21, STRING["dialogs.character.no_special_power"]);
- delaySeconds(3);
- } else if (item->_equipMode == NOT_EQUIPPABLE ||
- msg.keycode >= Common::KEYCODE_a) {
- if (invEntry->_charges) {
- // TODO: Handle charges
-
- } else {
- writeString(8, 21, STRING["dialogs.character.no_charges_left"]);
- delaySeconds(3);
- }
- }
+ if (dynamic_cast<Views::Combat *>(g_events->priorView()) != nullptr)
+ combatUseItem(*invEntry, msg.keycode >= Common::KEYCODE_a);
+ else
+ nonCombatUseItem(*invEntry, msg.keycode >= Common::KEYCODE_a);
break;
}
default:
@@ -552,6 +540,27 @@ void CharacterInfo::tradeHowMuch() {
);
}
+void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isBackpack) {
+ Item *item = getItem(invEntry._id);
+
+ clearLines(20, 24);
+ if (!item->_effectId) {
+ writeString(8, 21, STRING["dialogs.character.no_special_power"]);
+ delaySeconds(3);
+ } else if (item->_equipMode == NOT_EQUIPPABLE || isBackpack) {
+ if (invEntry._charges) {
+ // TODO: Handle charges
+
+ } else {
+ writeString(8, 21, STRING["dialogs.character.no_charges_left"]);
+ delaySeconds(3);
+ }
+ }
+}
+
+void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isBackpack) {
+
+}
} // namespace ViewsEnh
} // namespace MM1
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 7ed2fffad1f..a50f8d54fd3 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -24,6 +24,7 @@
#include "common/array.h"
#include "mm/mm1/views/character_base.h"
+#include "mm/mm1/data/character.h"
#include "mm/mm1/data/items.h"
#include "mm/mm1/views/text_entry.h"
@@ -66,6 +67,15 @@ private:
*/
void tradeHowMuch();
+ /**
+ * Using an item during combat
+ */
+ void combatUseItem(Inventory::Entry &invEntry, bool isBackpack);
+
+ /**
+ * Using an item outside of combat
+ */
+ void nonCombatUseItem(Inventory::Entry &invEntry, bool isBackpack);
public:
CharacterInfo() : CharacterBase("CharacterInfo") {}
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 2061bdab9fd..7bb6e3e0932 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -49,6 +49,13 @@ void Combat::setMode(Mode newMode) {
redraw();
}
+void Combat::disableAttacks() {
+ _allowFight = false;
+ _allowShoot = false;
+ _allowCast = false;
+ _allowAttack = false;
+}
+
bool Combat::msgFocus(const FocusMessage &msg) {
// Clear combat data
clear();
@@ -303,20 +310,20 @@ void Combat::writeAllOptions() {
bool canAttack = _canAttack[_currentChar];
if (canAttack) {
writeAttackOptions();
- _val5 = 'A';
- _val2 = 'F';
+ _allowAttack = true;
+ _allowFight = true;
// Archers can always attack
canAttack = g_globals->_currCharacter->_class == ARCHER;
}
if (canAttack && g_globals->_currCharacter->_missileAttr) {
- _val3 = 'S';
+ _allowShoot = true;
writeShootOption();
}
if (g_globals->_currCharacter->_sp._current) {
writeCastOption();
- _val4 = 'C';
+ _allowCast = true;
}
writeString(16, 22, STRING["dialogs.combat.exchange_use"]);
@@ -363,7 +370,8 @@ void Combat::writeShootOption() {
void Combat::resetBottom() {
clearLines(20, 24);
- _val2 = _val3 = _val4 = _val5 = 32;
+ _allowFight = _allowShoot = false;
+ _allowCast = _allowAttack = false;
}
void Combat::writeStaticContent() {
@@ -556,7 +564,7 @@ void Combat::checkMonsterSpellDone() {
}
void Combat::attack() {
- if (_val5 != 32)
+ if (_allowAttack)
attackMonsterPhysical();
}
@@ -574,7 +582,7 @@ void Combat::exchange() {
}
void Combat::fight() {
- if (_val2 != 32) {
+ if (_allowFight) {
if (_monsterList.size() < 2) {
attackMonsterPhysical();
} else {
@@ -587,7 +595,7 @@ void Combat::retreat() {
}
void Combat::shoot() {
- if (_val3 != 32) {
+ if (_allowShoot) {
if (_monsterList.size() < 2) {
attackMonsterPhysical();
} else {
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 6fa07d5b32e..e03e46683c9 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -204,6 +204,12 @@ public:
Combat();
virtual ~Combat() {}
+ /**
+ * Disable the flags for allowing attacks for
+ * the current character
+ */
+ void disableAttacks();
+
/**
* Called when the view is focused
*/
Commit: ee3f96d38e18790cf86bc298aa3280c1599ced08
https://github.com/scummvm/scummvm/commit/ee3f96d38e18790cf86bc298aa3280c1599ced08
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: More implementing character user item
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/globals.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index abf391af87e..42b621635b1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -51,9 +51,14 @@
how_much: "HOW MUCH:"
cast_spell: "CAST SPELL: LEVEL="
number: "NUMBER="
- use_no_special_power: "NO SPECIAL POWER"
- use_not_equipped: "NOT EQUIPPED"
- no_charges_left: "NO CHARGES LEFT"
+ use_combat:
+ use_no_special_power: "NO SPECIAL POWER"
+ use_not_equipped: "NOT EQUIPPED"
+ no_charges_left: "NO CHARGES LEFT"
+ use_noncombat:
+ no_special_power: "*** NO SPECIAL POWER ***"
+ not_equipped: "*** NOT EQUIPPED ***"
+ no_charges_left: "*** NO CHARGES LEFT ***"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 7f99055bdab..e5f19a73bd9 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -42,7 +42,7 @@ enum ItemCategory {
};
enum EquipMode {
- EQUIPMODE_0 = 0, NOT_EQUIPPABLE = 1,
+ EQUIPMODE_0 = 0, IS_EQUIPPABLE = 1,
EQUIP_CURSED = 0xff
};
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index acebf3a004a..06dcc0375cb 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -52,6 +52,7 @@ public:
Monsters _monsters;
byte _treasure[TREASURE_COUNT];
byte _delay = 5;
+ int _nonCombatEffectCtr = 0, _combatEffectCtr = 0;
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 34486bf992b..e0ff07fa989 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -321,7 +321,7 @@ void CharacterInfo::equipItem(uint index) {
}
if (equipError.empty()) {
- if (item._equipMode == NOT_EQUIPPABLE) {
+ if (item._equipMode == IS_EQUIPPABLE) {
equipError = STRING["dialogs.character.not_equipped"];
_textPos.x = 10;
}
@@ -371,7 +371,7 @@ void CharacterInfo::equipItem(uint index) {
uint freeIndex = c._equipped.add(itemId, item14);
if (item._equipMode != EQUIPMODE_0) {
- if (item._equipMode == NOT_EQUIPPABLE) {
+ if (item._equipMode == IS_EQUIPPABLE) {
equipError = STRING["dialogs.character.not_equipped"];
_textPos.x = 10;
} else if (item._equipMode == EQUIP_CURSED) {
@@ -540,26 +540,60 @@ void CharacterInfo::tradeHowMuch() {
);
}
-void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isBackpack) {
+void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
Item *item = getItem(invEntry._id);
+ Common::String msg;
- clearLines(20, 24);
if (!item->_effectId) {
- writeString(8, 21, STRING["dialogs.character.no_special_power"]);
- delaySeconds(3);
- } else if (item->_equipMode == NOT_EQUIPPABLE || isBackpack) {
+ msg = STRING["dialogs.character.use_combat.no_special_power"];
+
+ } else if (item->_equipMode == IS_EQUIPPABLE || isEquipped) {
if (invEntry._charges) {
// TODO: Handle charges
} else {
- writeString(8, 21, STRING["dialogs.character.no_charges_left"]);
- delaySeconds(3);
+ msg = STRING["dialogs.character.use_combat.no_charges_left"];
}
+ } else {
+ msg = STRING["dialogs.character.use_noncombat.not_equipped"];
}
+
+ clearLines(20, 24);
+ static_cast<Views::Combat *>(g_events->priorView())->disableAttacks();
+
+ writeString(8, 21, msg);
+ delaySeconds(3);
}
-void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isBackpack) {
+void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
+ Item *item = getItem(invEntry._id);
+ Common::String msg;
+
+ if (!item->_effectId) {
+ msg = STRING["dialogs.character.use_noncombat.no_special_power"];
+
+ } else if (item->_equipMode == IS_EQUIPPABLE || isEquipped) {
+ if (invEntry._charges) {
+ g_globals->_nonCombatEffectCtr++;
+ if (item->_effectId == 0xff) {
+ setSpell(item->_spellId, 0, 0);
+ Spells::cast(_spellIndex, g_globals->_currCharacter);
+
+ } else {
+
+ }
+ } else {
+ msg = STRING["dialogs.character.use_noncombat.no_charges_left"];
+ }
+ } else {
+ msg = STRING["dialogs.character.use_noncombat.not_equipped"];
+ }
+
+ clearLines(20, 24);
+ static_cast<Views::Combat *>(g_events->priorView())->disableAttacks();
+ writeString(9, 21, msg);
+ delaySeconds(3);
}
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index a50f8d54fd3..e8394574304 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -26,6 +26,7 @@
#include "mm/mm1/views/character_base.h"
#include "mm/mm1/data/character.h"
#include "mm/mm1/data/items.h"
+#include "mm/mm1/game/spell_casting.h"
#include "mm/mm1/views/text_entry.h"
namespace MM {
@@ -35,7 +36,7 @@ namespace Views {
/**
* In-game character dialog
*/
-class CharacterInfo : public CharacterBase {
+class CharacterInfo : public CharacterBase, MM1::Game::SpellCasting {
private:
enum ViewState {
DISPLAY, EQUIP, GATHER, REMOVE, SHARE,
@@ -70,12 +71,12 @@ private:
/**
* Using an item during combat
*/
- void combatUseItem(Inventory::Entry &invEntry, bool isBackpack);
+ void combatUseItem(Inventory::Entry &invEntry, bool isEquipped);
/**
* Using an item outside of combat
*/
- void nonCombatUseItem(Inventory::Entry &invEntry, bool isBackpack);
+ void nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped);
public:
CharacterInfo() : CharacterBase("CharacterInfo") {}
Commit: dcdef7a99f186ae7cd55d998aa4f782adbdff0d0
https://github.com/scummvm/scummvm/commit/dcdef7a99f186ae7cd55d998aa4f782adbdff0d0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:16+01:00
Commit Message:
MM: MM1: Further implementing use action
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/views/character_info.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 42b621635b1..9c848a3955c 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -55,10 +55,12 @@
use_no_special_power: "NO SPECIAL POWER"
use_not_equipped: "NOT EQUIPPED"
no_charges_left: "NO CHARGES LEFT"
+ done: "DONE"
use_noncombat:
no_special_power: "*** NO SPECIAL POWER ***"
not_equipped: "*** NOT EQUIPPED ***"
no_charges_left: "*** NO CHARGES LEFT ***"
+ done: "*** DONE ***"
create_characters:
title: "CREATE NEW CHARACTERS"
intellect: "INTELLECT...="
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 854dee5f12a..32628df10a1 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -93,6 +93,21 @@ void Inventory::removeAt(uint idx) {
_items.push_back(Entry());
}
+void Inventory::remove(Entry *e) {
+ int index = indexOf(e);
+ assert(index >= 0);
+ removeAt(index);
+}
+
+int Inventory::indexOf(Entry *e) {
+ for (uint i = 0; i < INVENTORY_COUNT; ++i) {
+ if (e == &_items[i])
+ return i;
+ }
+
+ return -1;
+}
+
bool Inventory::hasCategory(CategoryFn fn) const {
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
if (fn(_items[i]._id))
@@ -101,6 +116,14 @@ bool Inventory::hasCategory(CategoryFn fn) const {
return false;
}
+void Inventory::removeCharge(Entry *e) {
+ if (e->_charges) {
+ if (--e->_charges == 0)
+ remove(e);
+ }
+}
+
+
/*------------------------------------------------------------------------*/
void Character::synchronize(Common::Serializer &s) {
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 34c8f42db54..e12e1059f34 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -134,6 +134,22 @@ public:
*/
void removeAt(uint idx);
+ /**
+ * Remove an entry from the inventory
+ */
+ void remove(Entry *e);
+
+ /**
+ * Returns the index of a given entry
+ */
+ int indexOf(Entry *e);
+
+ /**
+ * Decreases the charge on a magic item, and removes
+ * it if the charges have run out
+ */
+ void removeCharge(Entry *e);
+
/**
* The following methods return true if any of
* the contained items are of the given category
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index e0ff07fa989..37e2ac57513 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -94,6 +94,8 @@ void CharacterInfo::draw() {
break;
case USE:
+ g_globals->_combatEffectCtr = 0;
+ g_globals->_nonCombatEffectCtr = 0;
writeString(7, 20, STRING["dialogs.character.use_what"]);
escToGoBack(0);
break;
@@ -549,13 +551,30 @@ void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
} else if (item->_equipMode == IS_EQUIPPABLE || isEquipped) {
if (invEntry._charges) {
- // TODO: Handle charges
+ g_globals->_combatEffectCtr++;
+ if (item->_effectId == 0xff) {
+ setSpell(item->_spellId, 0, 0);
+ Spells::cast(_spellIndex, g_globals->_currCharacter);
+
+ } else {
+ error("TODO: _effectId used as a character offset to increase attribute?");
+
+ if (g_globals->_combatEffectCtr)
+ (isEquipped ? &g_globals->_currCharacter->_equipped :
+ &g_globals->_currCharacter->_backpack)->removeCharge(&invEntry);
+ clearLines(20, 24);
+ writeString(14, 22, STRING["dialogs.character.use_combat.done"]);
+ Sound::sound(SOUND_2);
+ g_globals->_party.updateAC();
+ delaySeconds(2);
+ return;
+ }
} else {
msg = STRING["dialogs.character.use_combat.no_charges_left"];
}
} else {
- msg = STRING["dialogs.character.use_noncombat.not_equipped"];
+ msg = STRING["dialogs.character.use_combat.not_equipped"];
}
clearLines(20, 24);
@@ -580,7 +599,18 @@ void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped
Spells::cast(_spellIndex, g_globals->_currCharacter);
} else {
+ error("TODO: _effectId used as a character offset to increase attribute?");
+ if (g_globals->_nonCombatEffectCtr)
+ (isEquipped ? &g_globals->_currCharacter->_equipped :
+ &g_globals->_currCharacter->_backpack)->removeCharge(&invEntry);
+
+ clearLines(20, 24);
+ writeString(14, 22, STRING["spells.done"]);
+ Sound::sound(SOUND_2);
+ g_globals->_party.updateAC();
+ delaySeconds(2);
+ return;
}
} else {
msg = STRING["dialogs.character.use_noncombat.no_charges_left"];
Commit: 4f97b6f36e5cf5f738af131af10801b67e0bf478
https://github.com/scummvm/scummvm/commit/4f97b6f36e5cf5f738af131af10801b67e0bf478
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Hook up character info view to the combat use action
Changed paths:
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 37e2ac57513..48ffbe0d49e 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -105,6 +105,18 @@ void CharacterInfo::draw() {
}
}
+void CharacterInfo::timeout() {
+ switch (_state) {
+ case USE:
+ if (dynamic_cast<Views::Combat *>(g_events->priorView()) != nullptr) {
+ close();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
if (_state != DISPLAY) {
@@ -263,6 +275,17 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
return false;
}
+bool CharacterInfo::msgGame(const GameMessage &msg) {
+ if (msg._name == "USE") {
+ addView();
+ _state = USE;
+ redraw();
+ return true;
+ }
+
+ return false;
+}
+
void CharacterInfo::equipItem(uint index) {
Character &c = *g_globals->_currCharacter;
uint itemId = c._backpack[index]._id;
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index e8394574304..6a8fc92641c 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -83,8 +83,10 @@ public:
virtual ~CharacterInfo() {}
void draw() override;
+ void timeout() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
+ bool msgGame(const GameMessage &msg) override;
/**
* How much entry aborted
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 7bb6e3e0932..6fcec6a39e4 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -605,6 +605,8 @@ void Combat::shoot() {
}
void Combat::use() {
+ // Show the character info view in USE mode
+ g_events->send("CharacterInfo", GameMessage("USE"));
}
void Combat::writeMessage() {
Commit: b5ca82cfdca5cdf6396f6b1a269981777881bc2c
https://github.com/scummvm/scummvm/commit/b5ca82cfdca5cdf6396f6b1a269981777881bc2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Add actions for viewing characters info to combat view
Changed paths:
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 6fcec6a39e4..306125cd557 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -218,6 +218,21 @@ bool Combat::msgAction(const ActionMessage &msg) {
return false;
switch (msg._action) {
+ case KEYBIND_VIEW_PARTY1:
+ case KEYBIND_VIEW_PARTY2:
+ case KEYBIND_VIEW_PARTY3:
+ case KEYBIND_VIEW_PARTY4:
+ case KEYBIND_VIEW_PARTY5:
+ case KEYBIND_VIEW_PARTY6: {
+ uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
+ if (charNum < _party.size()) {
+ g_globals->_currCharacter = _party[charNum];
+ addView("CharacterInfo");
+ return true;
+ }
+ break;
+ }
+
case KEYBIND_COMBAT_ATTACK:
attack();
break;
Commit: 3a2203a464f3a8517f36dd9d1bda7d1474a7ef82
https://github.com/scummvm/scummvm/commit/3a2203a464f3a8517f36dd9d1bda7d1474a7ef82
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Properly handle character info use completion outside combat
Changed paths:
engines/mm/mm1/views/character_info.cpp
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 48ffbe0d49e..79225098e19 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -110,10 +110,13 @@ void CharacterInfo::timeout() {
case USE:
if (dynamic_cast<Views::Combat *>(g_events->priorView()) != nullptr) {
close();
+ } else {
+ _state = DISPLAY;
+ redraw();
}
break;
default:
- break;
+ return CharacterBase::timeout();
}
}
Commit: b3d7755704ddd0333afa1efdd921bbdf48e117e2
https://github.com/scummvm/scummvm/commit/b3d7755704ddd0333afa1efdd921bbdf48e117e2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Added a global flag for being in combat
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/globals.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/mm1.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/encounter.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9c848a3955c..3aa4588766f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -262,9 +262,6 @@
go_back: "'ESC' TO GO BACK"
no_characters: "NO AVAILABLE CHARACTERS"
some_characters: "AVAILABLE CHARACTERS"
- not_enough_gold: "*** NOT ENOUGH GOLD ***"
- not_enough_gems: "*** NOT ENOUGH GEMS ***"
- not_enough_sp: "*** NOT ENOUGH SPELL POINTS ***"
full: "*** BACKPACK FULL ***"
spells:
detect_charges: "MAGIC (CHARGES)"
@@ -748,11 +745,15 @@ movement:
view:
darkness: " DARKNESS"
spells:
- combat_only: "*** COMBAT ONLY ***"
- magic_doesnt_work: "*** MAGIC DOESN'T WORK HERE ***"
- outdoors_only: "*** OUTDOOR ONLY ***"
- failed: "*** SPELL FAILED ***"
- done: "*** DONE ***"
+ not_enough_gold: "NOT ENOUGH GOLD"
+ not_enough_gems: "NOT ENOUGH GEMS"
+ not_enough_sp: "NOT ENOUGH SPELL POINTS"
+ done: "DONE"
+ combat_only: "COMBAT ONLY"
+ magic_doesnt_work: "MAGIC DOESN'T WORK HERE"
+ outdoors_only: "OUTDOOR ONLY"
+ failed: "SPELL FAILED"
+
enter_to_cast: "'ENTER' TO CAST"
cast_on: "CAST ON: '1'-'%d'?"
which_town: "WHICH TOWN (1-5)?"
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 06dcc0375cb..e183bd7396e 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -53,6 +53,7 @@ public:
byte _treasure[TREASURE_COUNT];
byte _delay = 5;
int _nonCombatEffectCtr = 0, _combatEffectCtr = 0;
+ bool _inCombat = false;
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 2b092541017..a67d9bfbc93 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -125,5 +125,19 @@ bool MM1Engine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
+bool MM1Engine::canSaveGameStateCurrently() {
+ return !g_globals->_inCombat;
+}
+
+bool MM1Engine::canLoadGameStateCurrently() {
+ return true;
+}
+
+Common::Error MM1Engine::loadGameStream(Common::SeekableReadStream *stream) {
+ // TODO: Loading savegames
+ g_globals->_inCombat = false;
+ return Common::kNoError;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index a0943d83b7f..f5dc49de4b0 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -66,6 +66,18 @@ public:
Common::String getTargetName() const {
return _targetName;
}
+
+ /**
+ * Returns true if a game can be saved
+ */
+ bool canSaveGameStateCurrently() override;
+
+ /**
+ * Returns true if a savegame can be loaded
+ */
+ bool canLoadGameStateCurrently() override;
+
+ Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
};
extern MM1Engine *g_engine;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 306125cd557..d4579ddc78c 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -168,6 +168,7 @@ void Combat::timeout() {
spells._s.power_shield = 0;
close();
+ g_globals->_inCombat = false;
g_events->send("Game", GameMessage("UPDATE"));
return;
}
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 2ddb1b499dd..01b16ddbb03 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -34,6 +34,7 @@ Encounter::Encounter() : TextView("Encounter") {
bool Encounter::msgFocus(const FocusMessage &msg) {
_mode = ALERT;
+ g_globals->_inCombat = true;
return true;
}
@@ -252,6 +253,7 @@ bool Encounter::msgKeypress(const KeypressMessage &msg) {
void Encounter::encounterEnded() {
close();
+ g_globals->_inCombat = false;
g_events->send("Game", GameMessage("UPDATE"));
}
Commit: 9f9d9d5f7e75606fcf1576bd19b75fa889b070f4
https://github.com/scummvm/scummvm/commit/9f9d9d5f7e75606fcf1576bd19b75fa889b070f4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Non-combat spell messages match combat, but with stars
Changed paths:
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 77dd6a53396..d5f68a20d5b 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -131,18 +131,23 @@ bool SpellCasting::isMagicAllowed() const {
}
Common::String SpellCasting::getSpellError() const {
+ Common::String msg;
switch (_spellState) {
case SS_NOT_ENOUGH_SP:
- return STRING["spells.not_enough_sp"];
+ msg = STRING["spells.not_enough_sp"];
case SS_NOT_ENOUGH_GEMS:
- return STRING["spells.not_enough_gems"];
+ msg = STRING["spells.not_enough_gems"];
case SS_COMBAT_ONLY:
- return STRING["spells.combat_only"];
+ msg = STRING["spells.combat_only"];
case SS_OUTDOORS_ONLY:
- return STRING["spells.outdoors_only"];
+ msg = STRING["spells.outdoors_only"];
default:
- return STRING["spells.done"];
+ msg = STRING["spells.done"];
}
+
+ if (!g_globals->_inCombat)
+ msg = Common::String::format("*** %s ***", msg.c_str());
+ return msg;
}
} // namespace Game
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index a7d895a648f..2114c88933f 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -214,15 +214,15 @@ void CastSpell::performSpell(Character *chr) {
void CastSpell::spellDone() {
Common::String msg = getSpellError();
- int xp = 5;
-
+ int xp = 20 - (msg.size() / 2);
+/*
switch (getSpellState()) {
case Game::SS_NOT_ENOUGH_GEMS: xp = 9; break;
case Game::SS_COMBAT_ONLY: xp = 10; break;
case Game::SS_OUTDOORS_ONLY: xp = 10; break;
default: break;
}
-
+ */
spellDone(msg, xp);
}
Commit: 9a8dea21eccb1422db3cf57b10a046b47bd75fc6
https://github.com/scummvm/scummvm/commit/9a8dea21eccb1422db3cf57b10a046b47bd75fc6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Check for combat vs non-combat spells
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/game/spell_casting.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3aa4588766f..c07f1075462 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -750,6 +750,7 @@ spells:
not_enough_sp: "NOT ENOUGH SPELL POINTS"
done: "DONE"
combat_only: "COMBAT ONLY"
+ noncombat_only: "NON COMBAT ONLY"
magic_doesnt_work: "MAGIC DOESN'T WORK HERE"
outdoors_only: "OUTDOOR ONLY"
failed: "SPELL FAILED"
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index d5f68a20d5b..0fc87b4dca8 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -65,6 +65,7 @@ static const byte SPELL_FLAGS[47 * 2] = {
enum SpellFlag {
SF_COMBAT_ONLY = 1,
+ SF_NONCOMBAT_ONLY = 2,
SF_CAST_ON = 4,
SF_OUTDOORS_ONLY = 0x10
};
@@ -115,8 +116,10 @@ void SpellCasting::setSpell(int spellIndex, int requiredSp, int requiredGems) {
Maps::Map &map = *g_maps->_currentMap;
- if (SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
+ if (!g_globals->_inCombat && SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
_spellState = SS_COMBAT_ONLY;
+ else if (g_globals->_inCombat && SPELL_FLAGS[spellIndex] & SF_NONCOMBAT_ONLY)
+ _spellState = SS_NONCOMBAT_ONLY;
else if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) &&
!(map[Maps::MAP_ID] & 0x80))
_spellState = SS_OUTDOORS_ONLY;
diff --git a/engines/mm/mm1/game/spell_casting.h b/engines/mm/mm1/game/spell_casting.h
index 5cd7c1d8da7..40cc8a3cedd 100644
--- a/engines/mm/mm1/game/spell_casting.h
+++ b/engines/mm/mm1/game/spell_casting.h
@@ -30,7 +30,8 @@ namespace Game {
enum SpellState {
SS_OK, SS_NOT_ENOUGH_SP, SS_NOT_ENOUGH_GEMS,
- SS_COMBAT_ONLY, SS_DOESNT_WORK, SS_OUTDOORS_ONLY
+ SS_COMBAT_ONLY, SS_NONCOMBAT_ONLY, SS_DOESNT_WORK,
+ SS_OUTDOORS_ONLY
};
/**
Commit: da561aa2b7c325c32a0fce5d41591f3d7b8d7ada
https://github.com/scummvm/scummvm/commit/da561aa2b7c325c32a0fce5d41591f3d7b8d7ada
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Move spells logic into game/ folder
Changed paths:
A engines/mm/mm1/data/active_spells.cpp
A engines/mm/mm1/data/active_spells.h
A engines/mm/mm1/game/spells_party.cpp
A engines/mm/mm1/game/spells_party.h
R engines/mm/mm1/data/spells.cpp
R engines/mm/mm1/data/spells.h
engines/mm/mm1/console.cpp
engines/mm/mm1/data/game_state.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/spells/cast_spell.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 76b120170b1..9461a892aed 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -26,6 +26,7 @@
#include "mm/mm1/console.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/events.h"
+#include "mm/mm1/game/spells_party.h"
namespace MM {
namespace MM1 {
@@ -262,7 +263,7 @@ bool Console::cmdCast(int argc, const char **argv) {
int spellIndex = getSpellIndex(c, strToInt(argv[1]), strToInt(argv[2]));
setSpell(spellIndex, 0, 0);
- Spells::cast(_spellIndex, c);
+ Game::Spells::cast(_spellIndex, c);
return false;
}
}
diff --git a/engines/mm/mm1/data/active_spells.cpp b/engines/mm/mm1/data/active_spells.cpp
new file mode 100644
index 00000000000..74cb03a9dbf
--- /dev/null
+++ b/engines/mm/mm1/data/active_spells.cpp
@@ -0,0 +1,32 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/active_spells.h"
+
+namespace MM {
+namespace MM1 {
+
+void ActiveSpells::clear() {
+ Common::fill(&_arr[0], &_arr[ACTIVE_SPELLS_COUNT], 0);
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/active_spells.h b/engines/mm/mm1/data/active_spells.h
new file mode 100644
index 00000000000..56230c8a117
--- /dev/null
+++ b/engines/mm/mm1/data/active_spells.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_ACTIVE_SPELLS_H
+#define MM1_DATA_ACTIVE_SPELLS_H
+
+#include "mm/mm1/data/character.h"
+
+namespace MM {
+namespace MM1 {
+
+#define ACTIVE_SPELLS_COUNT 18
+
+struct ActiveSpellsStruct {
+ byte fear;
+ byte cold;
+ byte fire;
+ byte poison;
+ byte acid;
+ byte electricity;
+ byte magic;
+ byte light;
+ byte leather_skin;
+ byte levitate;
+ byte walk_on_water;
+ byte guard_dog;
+ byte psychic_protection;
+ byte bless;
+ byte invisbility;
+ byte shield;
+ byte power_shield;
+ byte cursed;
+};
+
+union ActiveSpells {
+ ActiveSpellsStruct _s;
+ byte _arr[ACTIVE_SPELLS_COUNT];
+
+ ActiveSpells() { clear(); }
+ void clear();
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index ab301c57009..00ed1d1c74c 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -27,7 +27,7 @@
#include "common/serializer.h"
#include "mm/mm1/data/character.h"
#include "mm/mm1/data/party.h"
-#include "mm/mm1/data/spells.h"
+#include "mm/mm1/data/active_spells.h"
namespace MM {
namespace MM1 {
diff --git a/engines/mm/mm1/data/spells.cpp b/engines/mm/mm1/game/spells_party.cpp
similarity index 98%
rename from engines/mm/mm1/data/spells.cpp
rename to engines/mm/mm1/game/spells_party.cpp
index 1a655fde90f..1806319431e 100644
--- a/engines/mm/mm1/data/spells.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -19,9 +19,9 @@
*
*/
-#include "mm/mm1/data/spells.h"
-#include "mm/mm1/data/locations.h"
+#include "mm/mm1/game/spells_party.h"
#include "mm/mm1/game/rest.h"
+#include "mm/mm1/data/locations.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
@@ -32,10 +32,7 @@
namespace MM {
namespace MM1 {
-
-void ActiveSpells::clear() {
- Common::fill(&_arr[0], &_arr[ACTIVE_SPELLS_COUNT], 0);
-}
+namespace Game {
Spells::SpellFn Spells::SPELLS[SPELLS_COUNT] = {
// Cleric spells
@@ -360,7 +357,7 @@ SpellResult Spells::cleric55_restoreEnergy(Character *chr) {
SpellResult Spells::cleric62_raiseDead(Character *chr) {
if ((chr->_condition == ERADICATED) ||
(chr->_condition & (BAD_CONDITION | DEAD)) ==
- (BAD_CONDITION | DEAD))
+ (BAD_CONDITION | DEAD))
return SR_FAILED;
int rnd = g_engine->getRandomNumber(100);
if (rnd == 100) {
@@ -420,7 +417,8 @@ SpellResult Spells::cleric65_townPortal(Character *chr) {
case Common::KEYCODE_2:
case Common::KEYCODE_3:
case Common::KEYCODE_4:
- case Common::KEYCODE_5: {
+ case Common::KEYCODE_5:
+ {
Maps::Maps &maps = *g_maps;
int townIndex = keyState.keycode - Common::KEYCODE_1;
@@ -494,10 +492,10 @@ SpellResult Spells::wizard24_jump(Character *chr) {
if ((map._states[maps._mapOffset] & maps._forwardMask & 0x55) != 0)
return SR_FAILED;
if ((map._walls[maps._mapOffset + maps._forwardOffset] &
- maps._forwardMask) != 0)
+ maps._forwardMask) != 0)
return SR_FAILED;
if ((map._states[maps._mapOffset + maps._forwardOffset]
- & maps._forwardMask & 0x55) != 0)
+ & maps._forwardMask & 0x55) != 0)
return SR_FAILED;
// The delta will be two steps in the facing direction.
@@ -606,5 +604,6 @@ void Spells::addLight(int amount) {
g_events->send("Game", GameMessage("UPDATE"));
}
+} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/spells.h b/engines/mm/mm1/game/spells_party.h
similarity index 86%
rename from engines/mm/mm1/data/spells.h
rename to engines/mm/mm1/game/spells_party.h
index 584178f33f4..fda3e6b25e3 100644
--- a/engines/mm/mm1/data/spells.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -19,19 +19,19 @@
*
*/
-#ifndef MM1_DATA_SPELLS_H
-#define MM1_DATA_SPELLS_H
+#ifndef MM1_GAME_SPELLS_H
+#define MM1_GAME_SPELLS_H
#include "mm/mm1/data/character.h"
namespace MM {
namespace MM1 {
+namespace Game {
#define SPELLS_COUNT (47 * 2)
-#define ACTIVE_SPELLS_COUNT 18
enum SpellResult {
- SR_SUCCESS_DONE, SR_SUCCESS_SILENT, SR_FAILED
+ SR_SUCCESS_DONE, SR_SUCCESS_SILENT, SR_FAILED
};
extern byte FLY_MAP_ID1[20];
@@ -39,38 +39,8 @@ extern byte FLY_MAP_ID2[20];
extern byte FLY_MAP_X[20];
extern byte FLY_MAP_Y[20];
-
-struct ActiveSpellsStruct {
- byte fear;
- byte cold;
- byte fire;
- byte poison;
- byte acid;
- byte electricity;
- byte magic;
- byte light;
- byte leather_skin;
- byte levitate;
- byte walk_on_water;
- byte guard_dog;
- byte psychic_protection;
- byte bless;
- byte invisbility;
- byte shield;
- byte power_shield;
- byte cursed;
-};
-
-union ActiveSpells {
- ActiveSpellsStruct _s;
- byte _arr[ACTIVE_SPELLS_COUNT];
-
- ActiveSpells() { clear(); }
- void clear();
-};
-
class Spells {
- typedef SpellResult (*SpellFn)(Character *chr);
+ typedef SpellResult(*SpellFn)(Character *chr);
private:
/**
* Restores an amount of Hp
@@ -82,7 +52,9 @@ private:
*/
static void addLight(int amount);
private:
- static SpellResult placeholder(Character *chr) { return SR_FAILED; }
+ static SpellResult placeholder(Character *chr) {
+ return SR_FAILED;
+ }
static SpellResult cleric14_firstAid(Character *chr);
static SpellResult cleric15_light(Character *chr);
static SpellResult cleric16_powerCure(Character *chr);
@@ -145,6 +117,7 @@ public:
static SpellResult cast(int spell, Character *chr);
};
+} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 79225098e19..1326a67e24f 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/combat.h"
+#include "mm/mm1/game/spells_party.h"
#include "mm/mm1/utils/strings.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
@@ -580,7 +581,7 @@ void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
g_globals->_combatEffectCtr++;
if (item->_effectId == 0xff) {
setSpell(item->_spellId, 0, 0);
- Spells::cast(_spellIndex, g_globals->_currCharacter);
+ Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
} else {
error("TODO: _effectId used as a character offset to increase attribute?");
@@ -622,7 +623,7 @@ void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped
g_globals->_nonCombatEffectCtr++;
if (item->_effectId == 0xff) {
setSpell(item->_spellId, 0, 0);
- Spells::cast(_spellIndex, g_globals->_currCharacter);
+ Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
} else {
error("TODO: _effectId used as a character offset to increase attribute?");
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index 2114c88933f..a275c9508f2 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views/spells/cast_spell.h"
+#include "mm/mm1/game/spells_party.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
@@ -194,13 +195,13 @@ void CastSpell::performSpell(Character *chr) {
spellDone(STRING["dialogs.misc.magic_doesnt_work"], 5);
} else {
// Cast the spell
- switch (MM1::Spells::cast(_spellIndex, chr)) {
- case SR_FAILED:
+ switch (Game::Spells::cast(_spellIndex, chr)) {
+ case Game::SR_FAILED:
// Spell failed
spellFailed();
break;
- case SR_SUCCESS_DONE:
+ case Game::SR_SUCCESS_DONE:
// Display spell done
spellDone();
break;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 3e0cde86076..6854df33861 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
mm1/meta_engine.o \
mm1/mm1.o \
mm1/sound.o \
+ mm1/data/active_spells.o \
mm1/data/character.o \
mm1/data/game_state.o \
mm1/data/items.o \
@@ -21,13 +22,13 @@ MODULE_OBJS := \
mm1/data/monsters.o \
mm1/data/party.o \
mm1/data/roster.o \
- mm1/data/spells.o \
mm1/game/game_logic.o \
mm1/game/combat.o \
mm1/game/encounter.o \
mm1/game/rest.o \
mm1/game/search.o \
mm1/game/spell_casting.o \
+ mm1/game/spells_party.o \
mm1/game/spells_monsters.o \
mm1/game/view_base.o \
mm1/gfx/dta.o \
Commit: 4b08b3c816e595f326201b218941b41f383321e8
https://github.com/scummvm/scummvm/commit/4b08b3c816e595f326201b218941b41f383321e8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:17+01:00
Commit Message:
MM: MM1: Start of combat spells
Changed paths:
engines/mm/mm1/data/game_state.cpp
engines/mm/mm1/data/game_state.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/rest.cpp
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/protect.cpp
engines/mm/mm1/views_enh/locations/temple.cpp
diff --git a/engines/mm/mm1/data/game_state.cpp b/engines/mm/mm1/data/game_state.cpp
index 7e3ca0ca2f8..4c00fe88658 100644
--- a/engines/mm/mm1/data/game_state.cpp
+++ b/engines/mm/mm1/data/game_state.cpp
@@ -26,7 +26,7 @@ namespace MM {
namespace MM1 {
GameState::GameState() {
- Common::fill(&_spells._arr[0], &_spells._arr[ACTIVE_SPELLS_COUNT], 0);
+ Common::fill(&_activeSpells._arr[0], &_activeSpells._arr[ACTIVE_SPELLS_COUNT], 0);
}
} // namespace MM1
diff --git a/engines/mm/mm1/data/game_state.h b/engines/mm/mm1/data/game_state.h
index 00ed1d1c74c..5bec41c6f7e 100644
--- a/engines/mm/mm1/data/game_state.h
+++ b/engines/mm/mm1/data/game_state.h
@@ -28,6 +28,7 @@
#include "mm/mm1/data/character.h"
#include "mm/mm1/data/party.h"
#include "mm/mm1/data/active_spells.h"
+#include "mm/mm1/data/spells_state.h"
namespace MM {
namespace MM1 {
@@ -38,7 +39,8 @@ namespace MM1 {
*/
struct GameState {
Party _party;
- ActiveSpells _spells;
+ ActiveSpells _activeSpells;
+ SpellsState _spellsState;
GameState();
};
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 3452ebde676..d08830fedaa 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -209,7 +209,7 @@ bool Combat::canMonsterCast() const {
}
void Combat::dispelParty() {
- g_globals->_spells.clear();
+ g_globals->_activeSpells.clear();
Character *tmpC = g_globals->_currCharacter;
Monster *tmpM = _monsterP;
@@ -774,12 +774,12 @@ void Combat::attackMonster(int monsterNum) {
MONFLAG_HELD | MONFLAG_WEBBED | MONFLAG_PARALYZED))
++_attackerLevel;
- if (g_globals->_spells._s.bless) {
+ if (g_globals->_activeSpells._s.bless) {
_attackerLevel++;
_attackAttr2._current++;
}
- if (g_globals->_spells._s.cursed) {
+ if (g_globals->_activeSpells._s.cursed) {
if (++_val11 > 255)
_val11 = 200;
}
diff --git a/engines/mm/mm1/game/rest.cpp b/engines/mm/mm1/game/rest.cpp
index aeb7fcee12e..60dc8cd7a7b 100644
--- a/engines/mm/mm1/game/rest.cpp
+++ b/engines/mm/mm1/game/rest.cpp
@@ -53,8 +53,8 @@ void Rest::check() {
void Rest::execute() {
// Reset active spells
- Common::fill(&g_globals->_spells._arr[0],
- &g_globals->_spells._arr[ACTIVE_SPELLS_COUNT], 0);
+ Common::fill(&g_globals->_activeSpells._arr[0],
+ &g_globals->_activeSpells._arr[ACTIVE_SPELLS_COUNT], 0);
// Rest the characters of the party
for (uint i = 0; i < g_globals->_party.size(); ++i) {
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 8d10fcccbcf..b5edd36541d 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -69,8 +69,10 @@ SpellsMonsters::SpellsMonsters() {
}
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
- _mmVal1 = _mmVal2 = _newCondition = 0;
- _resistanceType = RESISTANCE_MAGIC;
+ g_globals->_spellsState._mmVal1 = 0;
+ g_globals->_spellsState._mmVal2 = 0;
+ g_globals->_spellsState._resistanceType = RESISTANCE_MAGIC;
+ g_globals->_spellsState._newCondition = 0;
// All spell messages start with the monster who casts it
_lines.clear();
@@ -81,58 +83,58 @@ void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spe
void SpellsMonsters::spell01_curse() {
if (casts()) {
- add(STRING["monster_spells.a_curse"]);
- g_globals->_spells._s.cursed = MIN(255,
- (int)g_globals->_spells._s.cursed + 1);
+ add(STRING["monster_spellsState.a_curse"]);
+ g_globals->_activeSpells._s.cursed = MIN(255,
+ (int)g_globals->_activeSpells._s.cursed + 1);
}
}
void SpellsMonsters::spell02_energyBlast() {
if (casts()) {
- add(STRING["monster_spells.energy_blast"]);
- ++_mmVal1;
- _newCondition = getRandomNumber(16) + 4;
+ add(STRING["monster_spellsState.energy_blast"]);
+ ++g_globals->_spellsState._mmVal1;
+ g_globals->_spellsState._newCondition = getRandomNumber(16) + 4;
damageRandomChar();
}
}
void SpellsMonsters::spell03_fire() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.fire"].c_str()));
- ++_mmVal2;
- _resistanceType = RESISTANCE_FIRE;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.fire"].c_str()));
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
int count = g_globals->_encounters._arr1[getMonsterIndex()];
- _newCondition += count * 6;
+ g_globals->_spellsState._newCondition += count * 6;
damageRandomChar();
}
void SpellsMonsters::spell04_blindness() {
if (casts()) {
- add(STRING["monster_spells.blindness"]);
- ++_mmVal1;
- ++_mmVal2;
- _newCondition = 2;
+ add(STRING["monster_spellsState.blindness"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._newCondition = 2;
handlePartyEffects();
}
}
void SpellsMonsters::spell05_sprayPoison() {
- add(STRING["monster_spells.sprays_poison"]);
- ++_mmVal2;
- _resistanceType = RESISTANCE_POISON;
- _newCondition = POISONED;
+ add(STRING["monster_spellsState.sprays_poison"]);
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
+ g_globals->_spellsState._newCondition = POISONED;
handlePartyEffects();
}
void SpellsMonsters::spell06_sprayAcid() {
- add(STRING["monster_spells.sprays_acid"]);
- ++_mmVal2;
- _resistanceType = RESISTANCE_ACID;
- _newCondition = getRandomNumber((int)POISONED);
+ add(STRING["monster_spellsState.sprays_acid"]);
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_ACID;
+ g_globals->_spellsState._newCondition = getRandomNumber((int)POISONED);
add(':');
handlePartyDamage();
@@ -140,22 +142,22 @@ void SpellsMonsters::spell06_sprayAcid() {
void SpellsMonsters::spell07_sleep() {
if (casts()) {
- add(STRING["monster_spells.sleep"]);
- ++_mmVal1;
- ++_mmVal2;
- _resistanceType = RESISTANCE_PSYCHIC;
- _newCondition = ASLEEP;
+ add(STRING["monster_spellsState.sleep"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_PSYCHIC;
+ g_globals->_spellsState._newCondition = ASLEEP;
handlePartyEffects();
}
}
void SpellsMonsters::spell08_paralyze() {
if (casts()) {
- add(STRING["monster_spells.paralyze"]);
- ++_mmVal1;
- ++_mmVal2;
- _resistanceType = RESISTANCE_FEAR;
- _newCondition = PARALYZED;
+ add(STRING["monster_spellsState.paralyze"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_FEAR;
+ g_globals->_spellsState._newCondition = PARALYZED;
if (g_globals->_encounters._arr1[getMonsterIndex()] >= 5) {
handlePartyEffects();
@@ -168,38 +170,38 @@ void SpellsMonsters::spell08_paralyze() {
void SpellsMonsters::spell09_dispel() {
if (casts()) {
- add(STRING["monster_spells.dispel"]);
+ add(STRING["monster_spellsState.dispel"]);
dispelParty();
}
}
void SpellsMonsters::spell10_lightningBolt() {
if (casts()) {
- add(STRING["monster_spells.lightning_bolt"]);
- ++_mmVal1;
- ++_mmVal2;
- _resistanceType = RESISTANCE_ELECTRICITY;
- _newCondition = getRandomNumber(37) + 5;
+ add(STRING["monster_spellsState.lightning_bolt"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
+ g_globals->_spellsState._newCondition = getRandomNumber(37) + 5;
damageRandomChar();
}
}
void SpellsMonsters::spell11_strangeGas() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.strange_gas"].c_str()));
- ++_mmVal2;
- _resistanceType = RESISTANCE_POISON;
- _newCondition = BAD_CONDITION | STONE;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.strange_gas"].c_str()));
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
+ g_globals->_spellsState._newCondition = BAD_CONDITION | STONE;
handlePartyEffects();
}
void SpellsMonsters::spell12_explode() {
- add(STRING["monster_spells.explode"]);
- ++_mmVal2;
- _resistanceType = RESISTANCE_POISON;
- _newCondition = getRandomNumber(_arr1[getMonsterIndex()]);
+ add(STRING["monster_spellsState.explode"]);
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
+ g_globals->_spellsState._newCondition = getRandomNumber(_arr1[getMonsterIndex()]);
_arr1[getMonsterIndex()] = 0;
_monsterStatus[getMonsterIndex()] = MONFLAG_DEAD;
removeMonster();
@@ -210,15 +212,15 @@ void SpellsMonsters::spell12_explode() {
void SpellsMonsters::spell13_fireball() {
if (casts()) {
- add(STRING["monster_spells.fireball"]);
- ++_mmVal1;
- ++_mmVal2;
- _resistanceType = RESISTANCE_FIRE;
+ add(STRING["monster_spellsState.fireball"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
// This whole condition choice makes no sense
- _newCondition += 6 *
+ g_globals->_spellsState._newCondition += 6 *
g_globals->_encounters._arr1[getMonsterIndex()];
- _newCondition = getRandomNumber(_newCondition) + 4;
+ g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition) + 4;
add(':');
handlePartyDamage();
@@ -227,54 +229,54 @@ void SpellsMonsters::spell13_fireball() {
void SpellsMonsters::spell14_fireBreath() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.fire"].c_str()));
- ++_mmVal2;
- _resistanceType = RESISTANCE_FIRE;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.fire"].c_str()));
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
// This whole condition choice makes no sense
- _newCondition += 8 *
+ g_globals->_spellsState._newCondition += 8 *
g_globals->_encounters._arr1[getMonsterIndex()];
- _newCondition = getRandomNumber(_newCondition);
+ g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition);
add(':');
handlePartyDamage();
}
void SpellsMonsters::spell15_gazes() {
- add(STRING["monster_spells.gazes"]);
- ++_mmVal2;
- _newCondition = BAD_CONDITION | STONE;
+ add(STRING["monster_spellsState.gazes"]);
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._newCondition = BAD_CONDITION | STONE;
chooseCharacter();
writeConditionEffect();
}
void SpellsMonsters::spell16_acidArrow() {
- add(STRING["monster_spells.acid_arrow"]);
- ++_mmVal1;
- ++_mmVal2;
- _resistanceType = RESISTANCE_ACID;
- _newCondition = getRandomNumber(31) + 9;
+ add(STRING["monster_spellsState.acid_arrow"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_ACID;
+ g_globals->_spellsState._newCondition = getRandomNumber(31) + 9;
damageRandomChar();
}
void SpellsMonsters::spell17_elements() {
- add(STRING["monster_spells.call_elements"]);
- ++_mmVal2;
- _newCondition = getRandomNumber(21) + 39;
+ add(STRING["monster_spellsState.call_elements"]);
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._newCondition = getRandomNumber(21) + 39;
damageRandomChar();
}
void SpellsMonsters::spell18_coldBeam() {
if (casts()) {
- add(STRING["monster_spells.cold_beam"]);
- ++_mmVal1;
- ++_mmVal2;
- _resistanceType = RESISTANCE_COLD;
- _newCondition = getRandomNumber(41) + 9;
+ add(STRING["monster_spellsState.cold_beam"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._resistanceType = RESISTANCE_COLD;
+ g_globals->_spellsState._newCondition = getRandomNumber(41) + 9;
damageRandomChar();
}
@@ -282,9 +284,9 @@ void SpellsMonsters::spell18_coldBeam() {
void SpellsMonsters::spell19_dancingSword() {
if (casts()) {
- add(STRING["monster_spells.dancing_sword"]);
- ++_mmVal1;
- _newCondition = getRandomNumber(14) + 16;
+ add(STRING["monster_spellsState.dancing_sword"]);
+ ++g_globals->_spellsState._mmVal1;
+ g_globals->_spellsState._newCondition = getRandomNumber(14) + 16;
add(':');
handlePartyDamage();
@@ -292,7 +294,7 @@ void SpellsMonsters::spell19_dancingSword() {
}
void SpellsMonsters::spell20_magicDrain() {
- add(STRING["monster_spells.magic_drain"]);
+ add(STRING["monster_spellsState.magic_drain"]);
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
@@ -305,10 +307,10 @@ void SpellsMonsters::spell20_magicDrain() {
void SpellsMonsters::spell21_fingerOfDeath() {
if (casts()) {
- add(STRING["monster_spells.finger_of_death"]);
- ++_mmVal1;
- ++_mmVal2;
- _newCondition = BAD_CONDITION | DEAD;
+ add(STRING["monster_spellsState.finger_of_death"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._newCondition = BAD_CONDITION | DEAD;
chooseCharacter();
writeConditionEffect();
@@ -317,10 +319,10 @@ void SpellsMonsters::spell21_fingerOfDeath() {
void SpellsMonsters::spell22_sunRay() {
if (casts()) {
- add(STRING["monster_spells.sun_ray"]);
- ++_mmVal1;
- ++_mmVal2;
- _newCondition = getRandomNumber(51) + 49;
+ add(STRING["monster_spellsState.sun_ray"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._newCondition = getRandomNumber(51) + 49;
damageRandomChar();
}
@@ -328,10 +330,10 @@ void SpellsMonsters::spell22_sunRay() {
void SpellsMonsters::spell23_disintegration() {
if (casts()) {
- add(STRING["monster_spells.disintegration"]);
- ++_mmVal1;
- ++_mmVal2;
- _newCondition = ERADICATED;
+ add(STRING["monster_spellsState.disintegration"]);
+ ++g_globals->_spellsState._mmVal1;
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._newCondition = ERADICATED;
chooseCharacter();
writeConditionEffect();
@@ -339,18 +341,18 @@ void SpellsMonsters::spell23_disintegration() {
}
void SpellsMonsters::spell24_commandsEnergy() {
- add(STRING["monster_spells.commands_energy"]);
- _newCondition = SILENCED | PARALYZED | UNCONSCIOUS;
+ add(STRING["monster_spellsState.commands_energy"]);
+ g_globals->_spellsState._newCondition = SILENCED | PARALYZED | UNCONSCIOUS;
damageRandomChar();
}
void SpellsMonsters::spell25_poison() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.poison"].c_str()));
- _resistanceType = RESISTANCE_POISON;
- _newCondition = _arr1[getMonsterIndex()];
- ++_mmVal2;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.poison"].c_str()));
+ g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
+ g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ ++g_globals->_spellsState._mmVal2;
add(':');
handlePartyDamage();
@@ -358,11 +360,11 @@ void SpellsMonsters::spell25_poison() {
void SpellsMonsters::spell26_lightning() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.lightning"].c_str()));
- _resistanceType = RESISTANCE_ELECTRICITY;
- _newCondition = _arr1[getMonsterIndex()];
- ++_mmVal2;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.lightning"].c_str()));
+ g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
+ g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ ++g_globals->_spellsState._mmVal2;
add(':');
handlePartyDamage();
@@ -370,11 +372,11 @@ void SpellsMonsters::spell26_lightning() {
void SpellsMonsters::spell27_frost() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.frost"].c_str()));
- _resistanceType = RESISTANCE_COLD;
- _newCondition = _arr1[getMonsterIndex()];
- ++_mmVal2;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.frost"].c_str()));
+ g_globals->_spellsState._resistanceType = RESISTANCE_COLD;
+ g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ ++g_globals->_spellsState._mmVal2;
add(':');
handlePartyDamage();
@@ -382,11 +384,11 @@ void SpellsMonsters::spell27_frost() {
void SpellsMonsters::spell28_spikes() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.spikes"].c_str()));
- _resistanceType = RESISTANCE_ELECTRICITY;
- _newCondition = _arr1[getMonsterIndex()];
- ++_mmVal2;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.spikes"].c_str()));
+ g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
+ g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ ++g_globals->_spellsState._mmVal2;
add(':');
handlePartyDamage();
@@ -394,11 +396,11 @@ void SpellsMonsters::spell28_spikes() {
void SpellsMonsters::spell29_acid() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.acid"].c_str()));
- _resistanceType = RESISTANCE_ACID;
- _newCondition = _arr1[getMonsterIndex()];
- ++_mmVal2;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.acid"].c_str()));
+ g_globals->_spellsState._resistanceType = RESISTANCE_ACID;
+ g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ ++g_globals->_spellsState._mmVal2;
add(':');
handlePartyDamage();
@@ -406,29 +408,29 @@ void SpellsMonsters::spell29_acid() {
void SpellsMonsters::spell30_fire() {
add(Common::String::format("%s %s",
- STRING["monster_spells.breathes"].c_str(),
- STRING["monster_spells.fire"].c_str()));
- _resistanceType = RESISTANCE_FIRE;
- _newCondition = _arr1[getMonsterIndex()];
- ++_mmVal2;
+ STRING["monster_spellsState.breathes"].c_str(),
+ STRING["monster_spellsState.fire"].c_str()));
+ g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
+ g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ ++g_globals->_spellsState._mmVal2;
add(':');
handlePartyDamage();
}
void SpellsMonsters::spell31_energy() {
- add(STRING["monster_spells.energy"]);
- _newCondition = _arr1[getMonsterIndex()];
- ++_mmVal2;
+ add(STRING["monster_spellsState.energy"]);
+ g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ ++g_globals->_spellsState._mmVal2;
add(':');
handlePartyDamage();
}
void SpellsMonsters::spell32_swarm() {
- add(STRING["monster_spells.swarm"]);
- ++_mmVal2;
- _newCondition = getRandomNumber(12);
+ add(STRING["monster_spellsState.swarm"]);
+ ++g_globals->_spellsState._mmVal2;
+ g_globals->_spellsState._newCondition = getRandomNumber(12);
add(':');
handlePartyDamage();
@@ -436,10 +438,10 @@ void SpellsMonsters::spell32_swarm() {
bool SpellsMonsters::casts() {
if (canMonsterCast()) {
- add(STRING["monster_spells.casts"]);
+ add(STRING["monster_spellsState.casts"]);
return true;
} else {
- add(STRING["monster_spells.fails_to_cast"]);
+ add(STRING["monster_spellsState.fails_to_cast"]);
return false;
}
}
@@ -478,18 +480,18 @@ void SpellsMonsters::chooseCharacter() {
bool SpellsMonsters::isCharAffected() const {
int val = g_globals->_currCharacter->_resistances._s._magic._current +
- g_globals->_spells._s.magic;
+ g_globals->_activeSpells._s.magic;
return randomThreshold(val);
}
void SpellsMonsters::handleDamage() {
- _mmVal5 = 1;
- _damage = _newCondition;
+ g_globals->_spellsState._mmVal5 = 1;
+ _damage = g_globals->_spellsState._newCondition;
if (charAffected()) {
if (isEffective()) {
if (testElementalResistance()) {
- if (g_globals->_spells._s.power_shield)
+ if (g_globals->_activeSpells._s.power_shield)
_damage = 1;
writeDamage();
@@ -504,8 +506,8 @@ bool SpellsMonsters::charAffected() {
addCharName();
add(' ');
- if (_mmVal1 && !isCharAffected()) {
- _lines.back()._text += STRING["monster_spells.not_affected"];
+ if (g_globals->_spellsState._mmVal1 && !isCharAffected()) {
+ _lines.back()._text += STRING["monster_spellsState.not_affected"];
return false;
}
@@ -513,14 +515,14 @@ bool SpellsMonsters::charAffected() {
}
bool SpellsMonsters::isEffective() {
- if (_mmVal2) {
+ if (g_globals->_spellsState._mmVal2) {
proc9();
- if (_mmVal7) {
- if (_mmVal5) {
+ if (g_globals->_spellsState._mmVal7) {
+ if (g_globals->_spellsState._mmVal5) {
_damage >>= 1;
} else {
- _lines.back()._text += STRING["monster_spells.not_affected"];
+ _lines.back()._text += STRING["monster_spellsState.not_affected"];
return false;
}
}
@@ -532,7 +534,7 @@ bool SpellsMonsters::isEffective() {
bool SpellsMonsters::testElementalResistance() {
bool result = false;
- switch (_resistanceType) {
+ switch (g_globals->_spellsState._resistanceType) {
case RESISTANCE_FIRE:
result = damageType1(); break;
case RESISTANCE_COLD:
@@ -552,10 +554,10 @@ bool SpellsMonsters::testElementalResistance() {
}
if (!result) {
- if (_mmVal5) {
+ if (g_globals->_spellsState._mmVal5) {
_damage >>= 2;
} else {
- add(STRING["monster_spells.not_affected"]);
+ add(STRING["monster_spellsState.not_affected"]);
return false;
}
}
@@ -564,15 +566,15 @@ bool SpellsMonsters::testElementalResistance() {
}
void SpellsMonsters::writeDamage() {
- add(STRING["monster_spells.takes"]);
+ add(STRING["monster_spellsState.takes"]);
add(Common::String::format("%d ", _damage));
- add(STRING[_damage > 1 ? "monster_spells.points" : "monster_spells.point"]);
+ add(STRING[_damage > 1 ? "monster_spellsState.points" : "monster_spellsState.point"]);
add(' ');
if (_lines.back()._text.size() >= 30)
add('!');
else
- add(STRING["monster_spells.of_damage"]);
+ add(STRING["monster_spellsState.of_damage"]);
}
void SpellsMonsters::subtractDamage() {
@@ -589,7 +591,7 @@ void SpellsMonsters::subtractDamage() {
c._condition |= UNCONSCIOUS;
addCharName();
add(' ');
- add(STRING["monster_spells.goes_down"]);
+ add(STRING["monster_spellsState.goes_down"]);
Sound::sound2(SOUND_8);
} else {
@@ -599,7 +601,7 @@ void SpellsMonsters::subtractDamage() {
_lines.push_back(Line(0, 3, ""));
addCharName();
add(' ');
- add(STRING["monster_spells.dies"]);
+ add(STRING["monster_spellsState.dies"]);
Sound::sound2(SOUND_8);
}
}
@@ -612,51 +614,51 @@ void SpellsMonsters::proc9() {
val += 20;
int randVal = getRandomNumber(100);
- _mmVal7 = randVal < 99 && randVal <= val ? 1 : 0;
+ g_globals->_spellsState._mmVal7 = randVal < 99 && randVal <= val ? 1 : 0;
}
bool SpellsMonsters::damageType1() {
int threshold = g_globals->_currCharacter->_resistances._s._fire +
- g_globals->_spells._s.fire;
+ g_globals->_activeSpells._s.fire;
return randomThreshold(threshold);
}
bool SpellsMonsters::damageType2() {
int threshold = g_globals->_currCharacter->_resistances._s._cold +
- g_globals->_spells._s.cold;
+ g_globals->_activeSpells._s.cold;
return randomThreshold(threshold);
}
bool SpellsMonsters::damageType3() {
int threshold = g_globals->_currCharacter->_resistances._s._electricity +
- g_globals->_spells._s.electricity;
+ g_globals->_activeSpells._s.electricity;
return randomThreshold(threshold);
}
bool SpellsMonsters::damageType4() {
int threshold = g_globals->_currCharacter->_resistances._s._acid +
- g_globals->_spells._s.acid;
+ g_globals->_activeSpells._s.acid;
return randomThreshold(threshold);
}
bool SpellsMonsters::damageType5() {
- if (g_globals->_spells._s.psychic_protection) {
+ if (g_globals->_activeSpells._s.psychic_protection) {
return false;
} else {
int threshold = g_globals->_currCharacter->_resistances._s._fear +
- g_globals->_spells._s.fear;
+ g_globals->_activeSpells._s.fear;
return randomThreshold(threshold);
}
}
bool SpellsMonsters::damageType6() {
int threshold = g_globals->_currCharacter->_resistances._s._poison +
- g_globals->_spells._s.poison;
+ g_globals->_activeSpells._s.poison;
return randomThreshold(threshold);
}
bool SpellsMonsters::damageType7() {
- if (g_globals->_spells._s.psychic_protection) {
+ if (g_globals->_activeSpells._s.psychic_protection) {
return false;
} else {
int threshold = g_globals->_currCharacter->_resistances._s._psychic;
@@ -665,32 +667,32 @@ bool SpellsMonsters::damageType7() {
}
void SpellsMonsters::writeConditionEffect() {
- _mmVal5 = 0;
+ g_globals->_spellsState._mmVal5 = 0;
int effectNum;
if (!charAffected() || !isEffective() || !testElementalResistance())
return;
- if (_newCondition == 0) {
+ if (g_globals->_spellsState._newCondition == 0) {
effectNum = 10;
- } else if (_newCondition & BAD_CONDITION) {
- if (!(_newCondition & (BAD_CONDITION | DEAD)))
+ } else if (g_globals->_spellsState._newCondition & BAD_CONDITION) {
+ if (!(g_globals->_spellsState._newCondition & (BAD_CONDITION | DEAD)))
effectNum = 7;
- else if (!(_newCondition & (BAD_CONDITION | STONE)))
+ else if (!(g_globals->_spellsState._newCondition & (BAD_CONDITION | STONE)))
effectNum = 8;
- else if (_newCondition == ERADICATED)
+ else if (g_globals->_spellsState._newCondition == ERADICATED)
effectNum = 9;
else
effectNum = 10;
} else {
effectNum = 0;
- for (byte bitset = _newCondition; bitset & 1;
+ for (byte bitset = g_globals->_spellsState._newCondition; bitset & 1;
++effectNum, bitset >>= 1) {
}
}
- add(STRING[Common::String::format("monster_spells.effects.%d",
+ add(STRING[Common::String::format("monster_spellsState.effects.%d",
effectNum)]);
add('!');
}
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 9065d09306c..c2555ceec7f 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -41,11 +41,6 @@ class SpellsMonsters : public GameLogic {
private:
static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
LineArray _lines;
- int _mmVal1 = 0, _mmVal2 = 0;
- byte _newCondition = 0;
- int _mmVal5 = 0;
- int _mmVal7 = 0;
- Resistance _resistanceType = RESISTANCE_MAGIC;
void spell01_curse();
void spell02_energyBlast();
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 1806319431e..2c142fa8faa 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -166,6 +166,32 @@ SpellResult Spells::cast(int spell, Character *chr) {
return SPELLS[spell](chr);
}
+SpellResult Spells::cleric11_awaken(Character *chr) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._condition & BAD_CONDITION))
+ c._condition &= ~ASLEEP;
+ }
+
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric12_bless(Character *chr) {
+ g_globals->_activeSpells._s.bless++;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult Spells::cleric13_blind(Character *chr) {
+ SpellsState &s = g_globals->_spellsState;
+ s._mmVal1++;
+ s._mmVal2 = 7;
+ s._newCondition = BLINDED;
+ s._resistanceType = static_cast<Resistance>((int)s._resistanceType + 1);
+
+ iterateMonsters();
+ return SR_SUCCESS_DONE;
+}
+
SpellResult Spells::cleric14_firstAid(Character *chr) {
restoreHp(chr, 8);
return SR_SUCCESS_DONE;
@@ -186,7 +212,7 @@ SpellResult Spells::cleric16_powerCure(Character *chr) {
}
SpellResult Spells::cleric17_protectionFromFear(Character *chr) {
- g_globals->_spells._s.fear =
+ g_globals->_activeSpells._s.fear =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
@@ -197,19 +223,19 @@ SpellResult Spells::cleric21_cureWounds(Character *chr) {
}
SpellResult Spells::cleric24_protectionFromCold(Character *chr) {
- g_globals->_spells._s.cold =
+ g_globals->_activeSpells._s.cold =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult Spells::cleric25_protectionFromIce(Character *chr) {
- g_globals->_spells._s.fire =
+ g_globals->_activeSpells._s.fire =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult Spells::cleric26_protectionFromPoison(Character *chr) {
- g_globals->_spells._s.poison =
+ g_globals->_activeSpells._s.poison =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
@@ -253,8 +279,8 @@ SpellResult Spells::cleric37_removeQuest(Character *chr) {
}
SpellResult Spells::cleric38_walkOnWater(Character *chr) {
- g_globals->_spells._s.walk_on_water = MIN(
- (int)g_globals->_spells._s.walk_on_water + 1, 255);
+ g_globals->_activeSpells._s.walk_on_water = MIN(
+ (int)g_globals->_activeSpells._s.walk_on_water + 1, 255);
return SR_SUCCESS_DONE;
}
@@ -277,13 +303,13 @@ SpellResult Spells::cleric42_neutralizePoison(Character *chr) {
}
SpellResult Spells::cleric43_protectionFromAcid(Character *chr) {
- g_globals->_spells._s.acid =
+ g_globals->_activeSpells._s.acid =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult Spells::cleric44_protectionFromElectricity(Character *chr) {
- g_globals->_spells._s.electricity =
+ g_globals->_activeSpells._s.electricity =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
@@ -311,8 +337,8 @@ SpellResult Spells::cleric48_surface(Character *chr) {
SpellResult Spells::cleric52_dispelMagic(Character *chr) {
Maps::Map &map = *g_maps->_currentMap;
if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DISPEL_THRESHOLD]) {
- Common::fill(&g_globals->_spells._arr[0],
- &g_globals->_spells._arr[18], 0);
+ Common::fill(&g_globals->_activeSpells._arr[0],
+ &g_globals->_activeSpells._arr[18], 0);
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
@@ -446,7 +472,7 @@ SpellResult Spells::cleric73_protectionFromElements(Character *chr) {
int amount = g_globals->_currCharacter->_level._current + 25;
for (int i = 0; i < 6; ++i)
- g_globals->_spells._arr[i] = amount;
+ g_globals->_activeSpells._arr[i] = amount;
return SR_SUCCESS_DONE;
}
@@ -474,7 +500,7 @@ SpellResult Spells::wizard12_detectMagic(Character *chr) {
}
SpellResult Spells::wizard15_leatherSkin(Character *chr) {
- g_globals->_spells._s.leather_skin = g_globals->_currCharacter->_level._current;
+ g_globals->_activeSpells._s.leather_skin = g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
@@ -517,7 +543,7 @@ SpellResult Spells::wizard24_jump(Character *chr) {
}
SpellResult Spells::wizard25_levitate(Character *chr) {
- g_globals->_spells._s.levitate =
+ g_globals->_activeSpells._s.levitate =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
@@ -540,13 +566,13 @@ SpellResult Spells::wizard32_fly(Character *chr) {
}
SpellResult Spells::wizard45_guardDog(Character *chr) {
- g_globals->_spells._s.guard_dog =
+ g_globals->_activeSpells._s.guard_dog =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
SpellResult Spells::wizard46_psychicProtection(Character *chr) {
- g_globals->_spells._s.psychic_protection =
+ g_globals->_activeSpells._s.psychic_protection =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
@@ -573,7 +599,7 @@ SpellResult Spells::wizard63_etherialize(Character *chr) {
}
SpellResult Spells::wizard64_protectionFromMagic(Character *chr) {
- g_globals->_spells._s.magic =
+ g_globals->_activeSpells._s.magic =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
@@ -600,10 +626,14 @@ void Spells::restoreHp(Character *chr, uint16 hp) {
}
void Spells::addLight(int amount) {
- g_globals->_spells._s.light = MIN((int)g_globals->_spells._s.light + amount, 255);
+ g_globals->_activeSpells._s.light = MIN((int)g_globals->_activeSpells._s.light + amount, 255);
g_events->send("Game", GameMessage("UPDATE"));
}
+void Spells::iterateMonsters() {
+
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index fda3e6b25e3..5a66e1dcecd 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -51,10 +51,16 @@ private:
* Increases light duration
*/
static void addLight(int amount);
+
+ static void iterateMonsters();
+
private:
static SpellResult placeholder(Character *chr) {
return SR_FAILED;
}
+ static SpellResult cleric11_awaken(Character *chr);
+ static SpellResult cleric12_bless(Character *chr);
+ static SpellResult cleric13_blind(Character *chr);
static SpellResult cleric14_firstAid(Character *chr);
static SpellResult cleric15_light(Character *chr);
static SpellResult cleric16_powerCure(Character *chr);
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 742b9a5b8a6..613aae92a66 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -43,14 +43,14 @@ void ViewBase::update() {
_isDark = false;
if (maps._currentState & Maps::CELL_DARK) {
- if (g_globals->_spells._s.light) {
- g_globals->_spells._s.light--;
+ if (g_globals->_activeSpells._s.light) {
+ g_globals->_activeSpells._s.light--;
} else {
goto darkness;
}
}
- if ((map[Maps::MAP_FLAGS] & 1) && !g_globals->_spells._s.light) {
+ if ((map[Maps::MAP_FLAGS] & 1) && !g_globals->_activeSpells._s.light) {
darkness:
// TODO
_isDark = true;
@@ -165,7 +165,7 @@ void ViewBase::forward(KeybindingAction action) {
offset = 0;
if (map.dataByte(Maps::MAP_30 + offset) == 4 &&
- !g_globals->_spells._s.walk_on_water) {
+ !g_globals->_activeSpells._s.walk_on_water) {
Sound::sound(SOUND_1);
_dialogMessage = STRING["movement.obstructed.cant_swim"];
redraw();
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 6079737d2f3..9cfb3eb5340 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -303,13 +303,13 @@ void Map00::special22() {
void Map00::special23() {
Sound::sound(SOUND_2);
Common::String msg = STRING["maps.map00.trapdoor"];
- if (g_globals->_spells._s.levitate)
+ if (g_globals->_activeSpells._s.levitate)
msg += STRING["maps.map00.levitate"];
send(InfoMessage(msg,
[](const Common::KeyState &keyState) {
g_events->focusedView()->close();
- if (!g_globals->_spells._s.levitate)
+ if (!g_globals->_activeSpells._s.levitate)
g_maps->changeMap(0xa11, 1);
}
));
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index d4579ddc78c..c1b0aef1783 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -161,7 +161,7 @@ void Combat::timeout() {
checkMonsterSpellDone();
return;
case DEFEATED_MONSTERS: {
- auto &spells = g_globals->_spells;
+ auto &spells = g_globals->_activeSpells;
spells._s.bless = 0;
spells._s.invisbility = 0;
spells._s.shield = 0;
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 01b16ddbb03..eea13a90bc0 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -164,7 +164,7 @@ void Encounter::timeout() {
/* ENCOUNTER_OPTIONS */
g_engine->getRandomNumber(100) > map[Maps::MAP_21]) {
// Potentially surprised. Check for guard dog spell
- if (g_globals->_spells._s.guard_dog ||
+ if (g_globals->_activeSpells._s.guard_dog ||
g_engine->getRandomNumber(100) > map[Maps::MAP_20])
_mode = ENCOUNTER_OPTIONS;
else
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 5fb334eb7a1..32c295bd024 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -208,7 +208,7 @@ void Temple::donate() {
if (g_engine->getRandomNumber(15) == 10) {
for (int i = 0; i < 13; ++i)
- g_globals->_spells._arr[i] = 75;
+ g_globals->_activeSpells._arr[i] = 75;
Sound::sound(SOUND_3);
displayMessage(STRING["dialogs.temple.protected"]);
diff --git a/engines/mm/mm1/views/protect.cpp b/engines/mm/mm1/views/protect.cpp
index de2afc1b51f..2b935b82981 100644
--- a/engines/mm/mm1/views/protect.cpp
+++ b/engines/mm/mm1/views/protect.cpp
@@ -35,7 +35,7 @@ void Protect::draw() {
_textPos.x = 0;
_textPos.y = 2;
for (int i = 0; i < 7; ++i) {
- if (g_globals->_spells._arr[i]) {
+ if (g_globals->_activeSpells._arr[i]) {
printProtectionFrom();
writeString(STRING[Common::String::format(
"dialogs.protect.%d", i + 1)]);
@@ -44,9 +44,9 @@ void Protect::draw() {
}
// Light spell
- if (g_globals->_spells._arr[7]) {
+ if (g_globals->_activeSpells._arr[7]) {
writeString(STRING["dialogs.protect.8"]);
- writeNumber(g_globals->_spells._arr[7]);
+ writeNumber(g_globals->_activeSpells._arr[7]);
writeChar(')');
newLine();
}
@@ -56,7 +56,7 @@ void Protect::draw() {
if (i == 13)
newLine();
- if (g_globals->_spells._arr[i]) {
+ if (g_globals->_activeSpells._arr[i]) {
writeString(STRING[Common::String::format(
"dialogs.protect.%d", i + 1)]);
newLine();
@@ -66,8 +66,8 @@ void Protect::draw() {
--_textPos.y;
_textPos.x = 13;
- if (g_globals->_spells._arr[17]) {
- writeNumber(g_globals->_spells._arr[17]);
+ if (g_globals->_activeSpells._arr[17]) {
+ writeNumber(g_globals->_activeSpells._arr[17]);
_textPos.x++;
writeString(STRING["dialogs.protect.to_attacks"]);
}
@@ -83,7 +83,7 @@ void Protect::printProtectionLevel(uint protectIndex) {
_textPos.x = 24;
writeChar('+');
_textPos.x++;
- writeNumber(g_globals->_spells._arr[protectIndex]);
+ writeNumber(g_globals->_activeSpells._arr[protectIndex]);
writeChar('%');
newLine();
}
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
index 28a6e2aba14..ae3fa859976 100644
--- a/engines/mm/mm1/views_enh/locations/temple.cpp
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -212,7 +212,7 @@ void Temple::donate() {
if (g_engine->getRandomNumber(15) == 10) {
for (int i = 0; i < 13; ++i)
- g_globals->_spells._arr[i] = 75;
+ g_globals->_activeSpells._arr[i] = 75;
Sound::sound(SOUND_3);
displayMessage(STRING["dialogs.temple.protected"]);
Commit: c77d3e531eebb4d1e60d8a7f47ac9b2adf79bd1a
https://github.com/scummvm/scummvm/commit/c77d3e531eebb4d1e60d8a7f47ac9b2adf79bd1a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Skeleton classes for all the game maps
Changed paths:
A engines/mm/mm1/data/spells_state.h
A engines/mm/mm1/maps/map01.cpp
A engines/mm/mm1/maps/map01.h
A engines/mm/mm1/maps/map02.cpp
A engines/mm/mm1/maps/map02.h
A engines/mm/mm1/maps/map03.cpp
A engines/mm/mm1/maps/map03.h
A engines/mm/mm1/maps/map04.cpp
A engines/mm/mm1/maps/map04.h
A engines/mm/mm1/maps/map05.cpp
A engines/mm/mm1/maps/map05.h
A engines/mm/mm1/maps/map06.cpp
A engines/mm/mm1/maps/map06.h
A engines/mm/mm1/maps/map07.cpp
A engines/mm/mm1/maps/map07.h
A engines/mm/mm1/maps/map08.cpp
A engines/mm/mm1/maps/map08.h
A engines/mm/mm1/maps/map09.cpp
A engines/mm/mm1/maps/map09.h
A engines/mm/mm1/maps/map10.cpp
A engines/mm/mm1/maps/map10.h
A engines/mm/mm1/maps/map11.cpp
A engines/mm/mm1/maps/map11.h
A engines/mm/mm1/maps/map12.cpp
A engines/mm/mm1/maps/map12.h
A engines/mm/mm1/maps/map13.cpp
A engines/mm/mm1/maps/map13.h
A engines/mm/mm1/maps/map14.cpp
A engines/mm/mm1/maps/map14.h
A engines/mm/mm1/maps/map15.cpp
A engines/mm/mm1/maps/map15.h
A engines/mm/mm1/maps/map16.cpp
A engines/mm/mm1/maps/map16.h
A engines/mm/mm1/maps/map17.cpp
A engines/mm/mm1/maps/map17.h
A engines/mm/mm1/maps/map18.cpp
A engines/mm/mm1/maps/map18.h
A engines/mm/mm1/maps/map19.cpp
A engines/mm/mm1/maps/map19.h
A engines/mm/mm1/maps/map20.cpp
A engines/mm/mm1/maps/map20.h
A engines/mm/mm1/maps/map21.cpp
A engines/mm/mm1/maps/map21.h
A engines/mm/mm1/maps/map22.cpp
A engines/mm/mm1/maps/map22.h
A engines/mm/mm1/maps/map23.cpp
A engines/mm/mm1/maps/map23.h
A engines/mm/mm1/maps/map24.cpp
A engines/mm/mm1/maps/map24.h
A engines/mm/mm1/maps/map25.cpp
A engines/mm/mm1/maps/map25.h
A engines/mm/mm1/maps/map26.cpp
A engines/mm/mm1/maps/map26.h
A engines/mm/mm1/maps/map27.cpp
A engines/mm/mm1/maps/map27.h
A engines/mm/mm1/maps/map28.cpp
A engines/mm/mm1/maps/map28.h
A engines/mm/mm1/maps/map29.cpp
A engines/mm/mm1/maps/map29.h
A engines/mm/mm1/maps/map30.cpp
A engines/mm/mm1/maps/map30.h
A engines/mm/mm1/maps/map31.cpp
A engines/mm/mm1/maps/map31.h
A engines/mm/mm1/maps/map32.cpp
A engines/mm/mm1/maps/map32.h
A engines/mm/mm1/maps/map33.cpp
A engines/mm/mm1/maps/map33.h
A engines/mm/mm1/maps/map34.cpp
A engines/mm/mm1/maps/map34.h
A engines/mm/mm1/maps/map35.cpp
A engines/mm/mm1/maps/map35.h
A engines/mm/mm1/maps/map36.cpp
A engines/mm/mm1/maps/map36.h
A engines/mm/mm1/maps/map37.cpp
A engines/mm/mm1/maps/map37.h
A engines/mm/mm1/maps/map38.cpp
A engines/mm/mm1/maps/map38.h
A engines/mm/mm1/maps/map39.cpp
A engines/mm/mm1/maps/map39.h
A engines/mm/mm1/maps/map40.cpp
A engines/mm/mm1/maps/map40.h
A engines/mm/mm1/maps/map41.cpp
A engines/mm/mm1/maps/map41.h
A engines/mm/mm1/maps/map42.cpp
A engines/mm/mm1/maps/map42.h
A engines/mm/mm1/maps/map43.cpp
A engines/mm/mm1/maps/map43.h
A engines/mm/mm1/maps/map44.cpp
A engines/mm/mm1/maps/map44.h
A engines/mm/mm1/maps/map45.cpp
A engines/mm/mm1/maps/map45.h
A engines/mm/mm1/maps/map46.cpp
A engines/mm/mm1/maps/map46.h
A engines/mm/mm1/maps/map47.cpp
A engines/mm/mm1/maps/map47.h
A engines/mm/mm1/maps/map48.cpp
A engines/mm/mm1/maps/map48.h
A engines/mm/mm1/maps/map49.cpp
A engines/mm/mm1/maps/map49.h
A engines/mm/mm1/maps/map50.cpp
A engines/mm/mm1/maps/map50.h
A engines/mm/mm1/maps/map51.cpp
A engines/mm/mm1/maps/map51.h
A engines/mm/mm1/maps/map52.cpp
A engines/mm/mm1/maps/map52.h
A engines/mm/mm1/maps/map53.cpp
A engines/mm/mm1/maps/map53.h
A engines/mm/mm1/maps/map54.cpp
A engines/mm/mm1/maps/map54.h
engines/mm/mm1/maps/map00.h
engines/mm/mm1/maps/maps.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/data/spells_state.h b/engines/mm/mm1/data/spells_state.h
new file mode 100644
index 00000000000..b1ed76bcbc7
--- /dev/null
+++ b/engines/mm/mm1/data/spells_state.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_SPELLS_H
+#define MM1_DATA_SPELLS_H
+
+#include "mm/mm1/data/character.h"
+
+namespace MM {
+namespace MM1 {
+
+struct SpellsState {
+ int _mmVal1 = 0, _mmVal2 = 0;
+ int _mmVal5 = 0;
+ int _mmVal7 = 0;
+ Resistance _resistanceType = RESISTANCE_MAGIC;
+ byte _newCondition = 0;
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index 6e8f85322a4..04c465f211d 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MM1_MAPS_MAP0_H
-#define MM1_MAPS_MAP0_H
+#ifndef MM1_MAPS_MAP00_H
+#define MM1_MAPS_MAP00_H
#include "mm/mm1/maps/map.h"
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
new file mode 100644
index 00000000000..f1100542763
--- /dev/null
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map01.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map01::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map01::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map01.h b/engines/mm/mm1/maps/map01.h
new file mode 100644
index 00000000000..a28edf92391
--- /dev/null
+++ b/engines/mm/mm1/maps/map01.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP01_H
+#define MM1_MAPS_MAP01_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map01 : public Map {
+ typedef void (Map01:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map01::special00
+ };
+public:
+ Map01() : Map(1, "portsmit", 0xC03) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
new file mode 100644
index 00000000000..addeb197eac
--- /dev/null
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map02.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map02::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map02::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map02.h b/engines/mm/mm1/maps/map02.h
new file mode 100644
index 00000000000..69fe6a90441
--- /dev/null
+++ b/engines/mm/mm1/maps/map02.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP02_H
+#define MM1_MAPS_MAP02_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map02 : public Map {
+ typedef void (Map02:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map02::special00
+ };
+public:
+ Map02() : Map(2, "algary", 0x203) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
new file mode 100644
index 00000000000..70bef628241
--- /dev/null
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map03.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map03::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map03::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map03.h b/engines/mm/mm1/maps/map03.h
new file mode 100644
index 00000000000..8ece67d6093
--- /dev/null
+++ b/engines/mm/mm1/maps/map03.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP03_H
+#define MM1_MAPS_MAP03_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map03 : public Map {
+ typedef void (Map03:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map03::special00
+ };
+public:
+ Map03() : Map(3, "dusk", 0x802) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
new file mode 100644
index 00000000000..592c18e6628
--- /dev/null
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map04.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map04::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map04::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map04.h b/engines/mm/mm1/maps/map04.h
new file mode 100644
index 00000000000..2a8c49e0cf3
--- /dev/null
+++ b/engines/mm/mm1/maps/map04.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP04_H
+#define MM1_MAPS_MAP04_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map04 : public Map {
+ typedef void (Map04:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map04::special00
+ };
+public:
+ Map04() : Map(4, "erliquin", 0x0B1A) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
new file mode 100644
index 00000000000..662153a63d4
--- /dev/null
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map05.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map05::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map05::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map05.h b/engines/mm/mm1/maps/map05.h
new file mode 100644
index 00000000000..257d5974091
--- /dev/null
+++ b/engines/mm/mm1/maps/map05.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP05_H
+#define MM1_MAPS_MAP05_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map05 : public Map {
+ typedef void (Map05:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map05::special00
+ };
+public:
+ Map05() : Map(5, "cave1", 0x0A11) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
new file mode 100644
index 00000000000..fead3f5abb7
--- /dev/null
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map06.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map06::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map06::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map06.h b/engines/mm/mm1/maps/map06.h
new file mode 100644
index 00000000000..66db9c7447b
--- /dev/null
+++ b/engines/mm/mm1/maps/map06.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP06_H
+#define MM1_MAPS_MAP06_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map06 : public Map {
+ typedef void (Map06:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map06::special00
+ };
+public:
+ Map06() : Map(6, "cave2", 0x1) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
new file mode 100644
index 00000000000..33f88ffd64e
--- /dev/null
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map07.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map07::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map07::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map07.h b/engines/mm/mm1/maps/map07.h
new file mode 100644
index 00000000000..9fbf53c4bc0
--- /dev/null
+++ b/engines/mm/mm1/maps/map07.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP07_H
+#define MM1_MAPS_MAP07_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map07 : public Map {
+ typedef void (Map07:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map07::special00
+ };
+public:
+ Map07() : Map(7, "cave3", 0xC01) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
new file mode 100644
index 00000000000..f155bb6aa83
--- /dev/null
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map08.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map08::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map08::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map08.h b/engines/mm/mm1/maps/map08.h
new file mode 100644
index 00000000000..670cb6beddf
--- /dev/null
+++ b/engines/mm/mm1/maps/map08.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP08_H
+#define MM1_MAPS_MAP08_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map08 : public Map {
+ typedef void (Map08:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map08::special00
+ };
+public:
+ Map08() : Map(8, "cave4", 0x202) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
new file mode 100644
index 00000000000..b9ed15777bf
--- /dev/null
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map09.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map09::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map09::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map09.h b/engines/mm/mm1/maps/map09.h
new file mode 100644
index 00000000000..54749c57dd3
--- /dev/null
+++ b/engines/mm/mm1/maps/map09.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP09_H
+#define MM1_MAPS_MAP09_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map09 : public Map {
+ typedef void (Map09:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map09::special00
+ };
+public:
+ Map09() : Map(9, "cave5", 0x5) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
new file mode 100644
index 00000000000..82b7e70d603
--- /dev/null
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map10.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map10::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map10::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map10.h b/engines/mm/mm1/maps/map10.h
new file mode 100644
index 00000000000..fc0fdf88e88
--- /dev/null
+++ b/engines/mm/mm1/maps/map10.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP10_H
+#define MM1_MAPS_MAP10_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map10 : public Map {
+ typedef void (Map10:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map10::special00
+ };
+public:
+ Map10() : Map(10, "cave6", 0x51B) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
new file mode 100644
index 00000000000..286753d971d
--- /dev/null
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map11.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map11::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map11::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map11.h b/engines/mm/mm1/maps/map11.h
new file mode 100644
index 00000000000..7c19632c9e5
--- /dev/null
+++ b/engines/mm/mm1/maps/map11.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP11_H
+#define MM1_MAPS_MAP11_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map11 : public Map {
+ typedef void (Map11:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map11::special00
+ };
+public:
+ Map11() : Map(11, "cave7", 0x212) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
new file mode 100644
index 00000000000..edfe06ea0c0
--- /dev/null
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map12.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map12::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map12::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map12.h b/engines/mm/mm1/maps/map12.h
new file mode 100644
index 00000000000..00ac3ae775c
--- /dev/null
+++ b/engines/mm/mm1/maps/map12.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP12_H
+#define MM1_MAPS_MAP12_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map12 : public Map {
+ typedef void (Map12:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map12::special00
+ };
+public:
+ Map12() : Map(12, "cave8", 0x601) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map13.cpp b/engines/mm/mm1/maps/map13.cpp
new file mode 100644
index 00000000000..cf3895eec11
--- /dev/null
+++ b/engines/mm/mm1/maps/map13.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map13.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map13::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map13::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map13.h b/engines/mm/mm1/maps/map13.h
new file mode 100644
index 00000000000..99839bf7bdd
--- /dev/null
+++ b/engines/mm/mm1/maps/map13.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP13_H
+#define MM1_MAPS_MAP13_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map13 : public Map {
+ typedef void (Map13:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map13::special00
+ };
+public:
+ Map13() : Map(13, "cave9", 0xA00) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
new file mode 100644
index 00000000000..e9ff92c87ae
--- /dev/null
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map14.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map14::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map14::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map14.h b/engines/mm/mm1/maps/map14.h
new file mode 100644
index 00000000000..f26f3d5a40a
--- /dev/null
+++ b/engines/mm/mm1/maps/map14.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP14_H
+#define MM1_MAPS_MAP14_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map14 : public Map {
+ typedef void (Map14:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map14::special00
+ };
+public:
+ Map14() : Map(14, "areaa1", 0xF01) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
new file mode 100644
index 00000000000..5539afc2dcc
--- /dev/null
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map15.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map15::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map15::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map15.h b/engines/mm/mm1/maps/map15.h
new file mode 100644
index 00000000000..415729387b4
--- /dev/null
+++ b/engines/mm/mm1/maps/map15.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP15_H
+#define MM1_MAPS_MAP15_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map15 : public Map {
+ typedef void (Map15:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map15::special00
+ };
+public:
+ Map15() : Map(15, "areaa2", 0x502) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map16.cpp b/engines/mm/mm1/maps/map16.cpp
new file mode 100644
index 00000000000..3805235081c
--- /dev/null
+++ b/engines/mm/mm1/maps/map16.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map16.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map16::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map16::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map16.h b/engines/mm/mm1/maps/map16.h
new file mode 100644
index 00000000000..aa7985ee717
--- /dev/null
+++ b/engines/mm/mm1/maps/map16.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP16_H
+#define MM1_MAPS_MAP16_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map16 : public Map {
+ typedef void (Map16:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map16::special00
+ };
+public:
+ Map16() : Map(16, "areaa3", 0xB02) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
new file mode 100644
index 00000000000..5c741d37eab
--- /dev/null
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map17.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map17::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map17::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map17.h b/engines/mm/mm1/maps/map17.h
new file mode 100644
index 00000000000..2493f1a5e8b
--- /dev/null
+++ b/engines/mm/mm1/maps/map17.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP17_H
+#define MM1_MAPS_MAP17_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map17 : public Map {
+ typedef void (Map17:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map17::special00
+ };
+public:
+ Map17() : Map(17, "areaa4", 0x103) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
new file mode 100644
index 00000000000..73ab0340c4b
--- /dev/null
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map18.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map18::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map18::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map18.h b/engines/mm/mm1/maps/map18.h
new file mode 100644
index 00000000000..ce0c551fb94
--- /dev/null
+++ b/engines/mm/mm1/maps/map18.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP18_H
+#define MM1_MAPS_MAP18_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map18 : public Map {
+ typedef void (Map18:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map18::special00
+ };
+public:
+ Map18() : Map(18, "areab1", 0xA00) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map19.cpp b/engines/mm/mm1/maps/map19.cpp
new file mode 100644
index 00000000000..c2769c4ced6
--- /dev/null
+++ b/engines/mm/mm1/maps/map19.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map19.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map19::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map19::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map19.h b/engines/mm/mm1/maps/map19.h
new file mode 100644
index 00000000000..36cb532dae5
--- /dev/null
+++ b/engines/mm/mm1/maps/map19.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP19_H
+#define MM1_MAPS_MAP19_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map19 : public Map {
+ typedef void (Map19:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map19::special00
+ };
+public:
+ Map19() : Map(19, "areab2", 0x703) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
new file mode 100644
index 00000000000..b7a10f477f1
--- /dev/null
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map20.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map20::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map20::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map20.h b/engines/mm/mm1/maps/map20.h
new file mode 100644
index 00000000000..83b30d82f2a
--- /dev/null
+++ b/engines/mm/mm1/maps/map20.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP20_H
+#define MM1_MAPS_MAP20_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map20 : public Map {
+ typedef void (Map20:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map20::special00
+ };
+public:
+ Map20() : Map(20, "areab3", 0x101) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map21.cpp b/engines/mm/mm1/maps/map21.cpp
new file mode 100644
index 00000000000..58967765ad4
--- /dev/null
+++ b/engines/mm/mm1/maps/map21.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map21.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map21::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map21::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map21.h b/engines/mm/mm1/maps/map21.h
new file mode 100644
index 00000000000..367ccce7307
--- /dev/null
+++ b/engines/mm/mm1/maps/map21.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP21_H
+#define MM1_MAPS_MAP21_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map21 : public Map {
+ typedef void (Map21:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map21::special00
+ };
+public:
+ Map21() : Map(21, "areab4", 0xD03) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map22.cpp b/engines/mm/mm1/maps/map22.cpp
new file mode 100644
index 00000000000..9a19f480122
--- /dev/null
+++ b/engines/mm/mm1/maps/map22.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map22.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map22::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map22::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map22.h b/engines/mm/mm1/maps/map22.h
new file mode 100644
index 00000000000..f77e92e904f
--- /dev/null
+++ b/engines/mm/mm1/maps/map22.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP22_H
+#define MM1_MAPS_MAP22_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map22 : public Map {
+ typedef void (Map22:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map22::special00
+ };
+public:
+ Map22() : Map(22, "areac1", 0x304) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
new file mode 100644
index 00000000000..d0ec8cf64ad
--- /dev/null
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map23.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map23::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map23::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map23.h b/engines/mm/mm1/maps/map23.h
new file mode 100644
index 00000000000..5e10632957c
--- /dev/null
+++ b/engines/mm/mm1/maps/map23.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP23_H
+#define MM1_MAPS_MAP23_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map23 : public Map {
+ typedef void (Map23:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map23::special00
+ };
+public:
+ Map23() : Map(23, "areac2", 0xA11) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
new file mode 100644
index 00000000000..355e8b87777
--- /dev/null
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map24.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map24::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map24::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map24.h b/engines/mm/mm1/maps/map24.h
new file mode 100644
index 00000000000..632b45edd10
--- /dev/null
+++ b/engines/mm/mm1/maps/map24.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP24_H
+#define MM1_MAPS_MAP24_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map24 : public Map {
+ typedef void (Map24:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map24::special00
+ };
+public:
+ Map24() : Map(24, "areac3", 0x904) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
new file mode 100644
index 00000000000..17c69e653b1
--- /dev/null
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map25.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map25::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map25::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map25.h b/engines/mm/mm1/maps/map25.h
new file mode 100644
index 00000000000..881b3a90905
--- /dev/null
+++ b/engines/mm/mm1/maps/map25.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP25_H
+#define MM1_MAPS_MAP25_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map25 : public Map {
+ typedef void (Map25:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map25::special00
+ };
+public:
+ Map25() : Map(25, "areac4", 0xF04) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map26.cpp b/engines/mm/mm1/maps/map26.cpp
new file mode 100644
index 00000000000..a9425c0d96a
--- /dev/null
+++ b/engines/mm/mm1/maps/map26.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map26.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map26::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map26::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map26.h b/engines/mm/mm1/maps/map26.h
new file mode 100644
index 00000000000..f1691a8de51
--- /dev/null
+++ b/engines/mm/mm1/maps/map26.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP26_H
+#define MM1_MAPS_MAP26_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map26 : public Map {
+ typedef void (Map26:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map26::special00
+ };
+public:
+ Map26() : Map(26, "aread1", 0x505) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
new file mode 100644
index 00000000000..0a9ab5c7bf2
--- /dev/null
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map27.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map27::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map27::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map27.h b/engines/mm/mm1/maps/map27.h
new file mode 100644
index 00000000000..57a8921c999
--- /dev/null
+++ b/engines/mm/mm1/maps/map27.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP27_H
+#define MM1_MAPS_MAP27_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map27 : public Map {
+ typedef void (Map27:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map27::special00
+ };
+public:
+ Map27() : Map(27, "aread2", 0xB05) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map28.cpp b/engines/mm/mm1/maps/map28.cpp
new file mode 100644
index 00000000000..7787a062cc2
--- /dev/null
+++ b/engines/mm/mm1/maps/map28.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map28.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map28::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map28::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map28.h b/engines/mm/mm1/maps/map28.h
new file mode 100644
index 00000000000..2eacdc11c97
--- /dev/null
+++ b/engines/mm/mm1/maps/map28.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP28_H
+#define MM1_MAPS_MAP28_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map28 : public Map {
+ typedef void (Map28:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map28::special00
+ };
+public:
+ Map28() : Map(28, "aread3", 0x106) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
new file mode 100644
index 00000000000..12697e10412
--- /dev/null
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map29.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map29::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map29::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map29.h b/engines/mm/mm1/maps/map29.h
new file mode 100644
index 00000000000..e0a7e94894c
--- /dev/null
+++ b/engines/mm/mm1/maps/map29.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP29_H
+#define MM1_MAPS_MAP29_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map29 : public Map {
+ typedef void (Map29:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map29::special00
+ };
+public:
+ Map29() : Map(29, "aread4", 0x801) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
new file mode 100644
index 00000000000..ebf3c050e67
--- /dev/null
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map30.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map30::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map30::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map30.h b/engines/mm/mm1/maps/map30.h
new file mode 100644
index 00000000000..daa9637801e
--- /dev/null
+++ b/engines/mm/mm1/maps/map30.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP30_H
+#define MM1_MAPS_MAP30_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map30 : public Map {
+ typedef void (Map30:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map30::special00
+ };
+public:
+ Map30() : Map(30, "areae1", 0x112) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map31.cpp b/engines/mm/mm1/maps/map31.cpp
new file mode 100644
index 00000000000..427a65064d1
--- /dev/null
+++ b/engines/mm/mm1/maps/map31.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map31.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map31::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map31::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map31.h b/engines/mm/mm1/maps/map31.h
new file mode 100644
index 00000000000..26efc6c5fcb
--- /dev/null
+++ b/engines/mm/mm1/maps/map31.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP31_H
+#define MM1_MAPS_MAP31_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map31 : public Map {
+ typedef void (Map31:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map31::special00
+ };
+public:
+ Map31() : Map(31, "areae2", 0x706) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map32.cpp b/engines/mm/mm1/maps/map32.cpp
new file mode 100644
index 00000000000..9059c37c807
--- /dev/null
+++ b/engines/mm/mm1/maps/map32.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map32.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map32::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map32::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map32.h b/engines/mm/mm1/maps/map32.h
new file mode 100644
index 00000000000..31d3a0c56cf
--- /dev/null
+++ b/engines/mm/mm1/maps/map32.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP32_H
+#define MM1_MAPS_MAP32_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map32 : public Map {
+ typedef void (Map32:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map32::special00
+ };
+public:
+ Map32() : Map(32, "areae3", 0xB1A) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
new file mode 100644
index 00000000000..d447458570e
--- /dev/null
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map33.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map33::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map33::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map33.h b/engines/mm/mm1/maps/map33.h
new file mode 100644
index 00000000000..9d16d6c1495
--- /dev/null
+++ b/engines/mm/mm1/maps/map33.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP33_H
+#define MM1_MAPS_MAP33_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map33 : public Map {
+ typedef void (Map33:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map33::special00
+ };
+public:
+ Map33() : Map(33, "areae4", 0x11B) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map34.cpp b/engines/mm/mm1/maps/map34.cpp
new file mode 100644
index 00000000000..736f357126f
--- /dev/null
+++ b/engines/mm/mm1/maps/map34.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map34.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map34::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map34::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map34.h b/engines/mm/mm1/maps/map34.h
new file mode 100644
index 00000000000..9dfcf87618b
--- /dev/null
+++ b/engines/mm/mm1/maps/map34.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP34_H
+#define MM1_MAPS_MAP34_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map34 : public Map {
+ typedef void (Map34:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map34::special00
+ };
+public:
+ Map34() : Map(34, "doom", 0x706) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
new file mode 100644
index 00000000000..020ba2e4879
--- /dev/null
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map35.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map35::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map35::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map35.h b/engines/mm/mm1/maps/map35.h
new file mode 100644
index 00000000000..cf595cf44a0
--- /dev/null
+++ b/engines/mm/mm1/maps/map35.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP35_H
+#define MM1_MAPS_MAP35_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map35 : public Map {
+ typedef void (Map35:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map35::special00
+ };
+public:
+ Map35() : Map(35, "blackrn", 0xF08) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
new file mode 100644
index 00000000000..fe5680044e5
--- /dev/null
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map36.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map36::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map36::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map36.h b/engines/mm/mm1/maps/map36.h
new file mode 100644
index 00000000000..1c37a2a0241
--- /dev/null
+++ b/engines/mm/mm1/maps/map36.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP36_H
+#define MM1_MAPS_MAP36_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map36 : public Map {
+ typedef void (Map36:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map36::special00
+ };
+public:
+ Map36() : Map(36, "blackrs", 0x508) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
new file mode 100644
index 00000000000..4da3ffc4366
--- /dev/null
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map37.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map37::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map37::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map37.h b/engines/mm/mm1/maps/map37.h
new file mode 100644
index 00000000000..46bd5cf8ba7
--- /dev/null
+++ b/engines/mm/mm1/maps/map37.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP37_H
+#define MM1_MAPS_MAP37_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map37 : public Map {
+ typedef void (Map37:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map37::special00
+ };
+public:
+ Map37() : Map(37, "qvl1", 0xF03) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map38.cpp b/engines/mm/mm1/maps/map38.cpp
new file mode 100644
index 00000000000..2176d6a85e3
--- /dev/null
+++ b/engines/mm/mm1/maps/map38.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map38.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map38::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map38::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map38.h b/engines/mm/mm1/maps/map38.h
new file mode 100644
index 00000000000..dc672b61448
--- /dev/null
+++ b/engines/mm/mm1/maps/map38.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP38_H
+#define MM1_MAPS_MAP38_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map38 : public Map {
+ typedef void (Map38:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map38::special00
+ };
+public:
+ Map38() : Map(38, "qvl2", 0x703) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map39.cpp b/engines/mm/mm1/maps/map39.cpp
new file mode 100644
index 00000000000..2fad5186a05
--- /dev/null
+++ b/engines/mm/mm1/maps/map39.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map39.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map39::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map39::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map39.h b/engines/mm/mm1/maps/map39.h
new file mode 100644
index 00000000000..e42a8a4047a
--- /dev/null
+++ b/engines/mm/mm1/maps/map39.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP39_H
+#define MM1_MAPS_MAP39_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map39 : public Map {
+ typedef void (Map39:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map39::special00
+ };
+public:
+ Map39() : Map(39, "rwl1", 0xF02) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map40.cpp b/engines/mm/mm1/maps/map40.cpp
new file mode 100644
index 00000000000..bdd1a922ea7
--- /dev/null
+++ b/engines/mm/mm1/maps/map40.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map40.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map40::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map40::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map40.h b/engines/mm/mm1/maps/map40.h
new file mode 100644
index 00000000000..78d383375a5
--- /dev/null
+++ b/engines/mm/mm1/maps/map40.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP40_H
+#define MM1_MAPS_MAP40_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map40 : public Map {
+ typedef void (Map40:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map40::special00
+ };
+public:
+ Map40() : Map(40, "rwl2", 0x702) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map41.cpp b/engines/mm/mm1/maps/map41.cpp
new file mode 100644
index 00000000000..f0aff9f6e0d
--- /dev/null
+++ b/engines/mm/mm1/maps/map41.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map41.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map41::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map41::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map41.h b/engines/mm/mm1/maps/map41.h
new file mode 100644
index 00000000000..2feeb4c47f2
--- /dev/null
+++ b/engines/mm/mm1/maps/map41.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP41_H
+#define MM1_MAPS_MAP41_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map41 : public Map {
+ typedef void (Map41:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map41::special00
+ };
+public:
+ Map41() : Map(41, "enf1", 0xF04) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
new file mode 100644
index 00000000000..1571af74ceb
--- /dev/null
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map42.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map42::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map42::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map42.h b/engines/mm/mm1/maps/map42.h
new file mode 100644
index 00000000000..e0d0ae68954
--- /dev/null
+++ b/engines/mm/mm1/maps/map42.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP42_H
+#define MM1_MAPS_MAP42_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map42 : public Map {
+ typedef void (Map42:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map42::special00
+ };
+public:
+ Map42() : Map(42, "enf2", 0x704) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
new file mode 100644
index 00000000000..051b8e0694d
--- /dev/null
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map43.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map43::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map43::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map43.h b/engines/mm/mm1/maps/map43.h
new file mode 100644
index 00000000000..4297236b737
--- /dev/null
+++ b/engines/mm/mm1/maps/map43.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP43_H
+#define MM1_MAPS_MAP43_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map43 : public Map {
+ typedef void (Map43:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map43::special00
+ };
+public:
+ Map43() : Map(43, "whitew", 0xA11) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map44.cpp b/engines/mm/mm1/maps/map44.cpp
new file mode 100644
index 00000000000..b0b0847e813
--- /dev/null
+++ b/engines/mm/mm1/maps/map44.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map44.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map44::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map44::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map44.h b/engines/mm/mm1/maps/map44.h
new file mode 100644
index 00000000000..e7403ab7ba1
--- /dev/null
+++ b/engines/mm/mm1/maps/map44.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP44_H
+#define MM1_MAPS_MAP44_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map44 : public Map {
+ typedef void (Map44:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map44::special00
+ };
+public:
+ Map44() : Map(44, "dragad", 0x107) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map45.cpp b/engines/mm/mm1/maps/map45.cpp
new file mode 100644
index 00000000000..55542944f3d
--- /dev/null
+++ b/engines/mm/mm1/maps/map45.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map45.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map45::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map45::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map45.h b/engines/mm/mm1/maps/map45.h
new file mode 100644
index 00000000000..8c5aa06ae5d
--- /dev/null
+++ b/engines/mm/mm1/maps/map45.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP45_H
+#define MM1_MAPS_MAP45_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map45 : public Map {
+ typedef void (Map45:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map45::special00
+ };
+public:
+ Map45() : Map(45, "udrag1", 0xF05) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map46.cpp b/engines/mm/mm1/maps/map46.cpp
new file mode 100644
index 00000000000..202d96b192d
--- /dev/null
+++ b/engines/mm/mm1/maps/map46.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map46.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map46::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map46::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map46.h b/engines/mm/mm1/maps/map46.h
new file mode 100644
index 00000000000..4c5239c9c5c
--- /dev/null
+++ b/engines/mm/mm1/maps/map46.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP46_H
+#define MM1_MAPS_MAP46_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map46 : public Map {
+ typedef void (Map46:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map46::special00
+ };
+public:
+ Map46() : Map(46, "udrag2", 0xA00) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map47.cpp b/engines/mm/mm1/maps/map47.cpp
new file mode 100644
index 00000000000..8247ab7c187
--- /dev/null
+++ b/engines/mm/mm1/maps/map47.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map47.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map47::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map47::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map47.h b/engines/mm/mm1/maps/map47.h
new file mode 100644
index 00000000000..5b863168c2c
--- /dev/null
+++ b/engines/mm/mm1/maps/map47.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP47_H
+#define MM1_MAPS_MAP47_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map47 : public Map {
+ typedef void (Map47:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map47::special00
+ };
+public:
+ Map47() : Map(47, "udrag3", 0x705) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map48.cpp b/engines/mm/mm1/maps/map48.cpp
new file mode 100644
index 00000000000..b941a5e65b6
--- /dev/null
+++ b/engines/mm/mm1/maps/map48.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map48.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map48::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map48::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map48.h b/engines/mm/mm1/maps/map48.h
new file mode 100644
index 00000000000..8910178103c
--- /dev/null
+++ b/engines/mm/mm1/maps/map48.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP48_H
+#define MM1_MAPS_MAP48_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map48 : public Map {
+ typedef void (Map48:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map48::special00
+ };
+public:
+ Map48() : Map(48, "demon", 0x412) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
new file mode 100644
index 00000000000..9e221c31591
--- /dev/null
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map49.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map49::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map49::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map49.h b/engines/mm/mm1/maps/map49.h
new file mode 100644
index 00000000000..fd9e2760a80
--- /dev/null
+++ b/engines/mm/mm1/maps/map49.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP49_H
+#define MM1_MAPS_MAP49_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map49 : public Map {
+ typedef void (Map49:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map49::special00
+ };
+public:
+ Map49() : Map(49, "alamar", 0xB07) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map50.cpp b/engines/mm/mm1/maps/map50.cpp
new file mode 100644
index 00000000000..785aed40645
--- /dev/null
+++ b/engines/mm/mm1/maps/map50.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map50.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map50::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map50::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map50.h b/engines/mm/mm1/maps/map50.h
new file mode 100644
index 00000000000..72c7bf7ef2c
--- /dev/null
+++ b/engines/mm/mm1/maps/map50.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP50_H
+#define MM1_MAPS_MAP50_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map50 : public Map {
+ typedef void (Map50:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map50::special00
+ };
+public:
+ Map50() : Map(50, "pp1", 0xF01) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map51.cpp b/engines/mm/mm1/maps/map51.cpp
new file mode 100644
index 00000000000..bccc0187968
--- /dev/null
+++ b/engines/mm/mm1/maps/map51.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map51.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map51::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map51::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map51.h b/engines/mm/mm1/maps/map51.h
new file mode 100644
index 00000000000..b40a9dcb40a
--- /dev/null
+++ b/engines/mm/mm1/maps/map51.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP51_H
+#define MM1_MAPS_MAP51_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map51 : public Map {
+ typedef void (Map51:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map51::special00
+ };
+public:
+ Map51() : Map(51, "pp2", 0x701) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map52.cpp b/engines/mm/mm1/maps/map52.cpp
new file mode 100644
index 00000000000..dfefb6d9594
--- /dev/null
+++ b/engines/mm/mm1/maps/map52.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map52.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map52::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map52::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map52.h b/engines/mm/mm1/maps/map52.h
new file mode 100644
index 00000000000..f4c942dd7d7
--- /dev/null
+++ b/engines/mm/mm1/maps/map52.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP52_H
+#define MM1_MAPS_MAP52_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map52 : public Map {
+ typedef void (Map52:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map52::special00
+ };
+public:
+ Map52() : Map(52, "pp3", 0xE00) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map53.cpp b/engines/mm/mm1/maps/map53.cpp
new file mode 100644
index 00000000000..55680c8f79c
--- /dev/null
+++ b/engines/mm/mm1/maps/map53.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map53.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map53::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map53::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map53.h b/engines/mm/mm1/maps/map53.h
new file mode 100644
index 00000000000..518d50e525c
--- /dev/null
+++ b/engines/mm/mm1/maps/map53.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP53_H
+#define MM1_MAPS_MAP53_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map53 : public Map {
+ typedef void (Map53:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map53::special00
+ };
+public:
+ Map53() : Map(53, "pp4", 0x201) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
new file mode 100644
index 00000000000..ef231be56a4
--- /dev/null
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map54.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void Map54::special() {
+ // Scan for special actions on the map cell
+ for (uint i = 0; i < _data[50]; ++i) {
+ if (g_maps->_mapOffset == _data[51 + i]) {
+ // Found a specially handled cell, but it
+ // only triggers in designated direction(s)
+ if (g_maps->_forwardMask & _data[75 + i]) {
+ // TODO: Some extra message code
+ (this->*SPECIAL_FN[i])();
+ } else {
+ checkPartyDead();
+ }
+ return;
+ }
+ }
+/*
+ // All other cells on the map are encounters
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ */
+}
+
+void Map54::special00() {
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map54.h b/engines/mm/mm1/maps/map54.h
new file mode 100644
index 00000000000..12126ed668d
--- /dev/null
+++ b/engines/mm/mm1/maps/map54.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP54_H
+#define MM1_MAPS_MAP54_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class Map54 : public Map {
+ typedef void (Map54:: *SpecialFn)();
+private:
+ void special00();
+
+ const SpecialFn SPECIAL_FN[1] = {
+ &Map54::special00
+ };
+public:
+ Map54() : Map(54, "astral", 0xB1A) {}
+
+ /**
+ * Handles all special stuff that happens on the map
+ */
+ void special() override;
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 40d22e72383..0f6db05d709 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -27,6 +27,60 @@
#include "mm/mm1/gfx/screen_decoder.h"
#include "mm/mm1/maps/maps.h"
#include "mm/mm1/maps/map00.h"
+#include "mm/mm1/maps/map01.h"
+#include "mm/mm1/maps/map02.h"
+#include "mm/mm1/maps/map03.h"
+#include "mm/mm1/maps/map04.h"
+#include "mm/mm1/maps/map05.h"
+#include "mm/mm1/maps/map06.h"
+#include "mm/mm1/maps/map07.h"
+#include "mm/mm1/maps/map08.h"
+#include "mm/mm1/maps/map09.h"
+#include "mm/mm1/maps/map10.h"
+#include "mm/mm1/maps/map11.h"
+#include "mm/mm1/maps/map12.h"
+#include "mm/mm1/maps/map13.h"
+#include "mm/mm1/maps/map14.h"
+#include "mm/mm1/maps/map15.h"
+#include "mm/mm1/maps/map16.h"
+#include "mm/mm1/maps/map17.h"
+#include "mm/mm1/maps/map18.h"
+#include "mm/mm1/maps/map19.h"
+#include "mm/mm1/maps/map20.h"
+#include "mm/mm1/maps/map21.h"
+#include "mm/mm1/maps/map22.h"
+#include "mm/mm1/maps/map23.h"
+#include "mm/mm1/maps/map24.h"
+#include "mm/mm1/maps/map25.h"
+#include "mm/mm1/maps/map26.h"
+#include "mm/mm1/maps/map27.h"
+#include "mm/mm1/maps/map28.h"
+#include "mm/mm1/maps/map29.h"
+#include "mm/mm1/maps/map30.h"
+#include "mm/mm1/maps/map31.h"
+#include "mm/mm1/maps/map32.h"
+#include "mm/mm1/maps/map33.h"
+#include "mm/mm1/maps/map34.h"
+#include "mm/mm1/maps/map35.h"
+#include "mm/mm1/maps/map36.h"
+#include "mm/mm1/maps/map37.h"
+#include "mm/mm1/maps/map38.h"
+#include "mm/mm1/maps/map39.h"
+#include "mm/mm1/maps/map40.h"
+#include "mm/mm1/maps/map41.h"
+#include "mm/mm1/maps/map42.h"
+#include "mm/mm1/maps/map43.h"
+#include "mm/mm1/maps/map44.h"
+#include "mm/mm1/maps/map45.h"
+#include "mm/mm1/maps/map46.h"
+#include "mm/mm1/maps/map47.h"
+#include "mm/mm1/maps/map48.h"
+#include "mm/mm1/maps/map49.h"
+#include "mm/mm1/maps/map50.h"
+#include "mm/mm1/maps/map51.h"
+#include "mm/mm1/maps/map52.h"
+#include "mm/mm1/maps/map53.h"
+#include "mm/mm1/maps/map54.h"
namespace MM {
namespace MM1 {
@@ -35,74 +89,6 @@ Maps::Maps *g_maps;
namespace Maps {
-/** PLACEHOLDER MAPS **/
-#define PLACEHOLDER(SUFFIX, INDEX, NAME, ID) \
- class Map##SUFFIX : public Map { \
- public: \
- Map##SUFFIX() : Map(INDEX, NAME, ID) {} \
- void special() override {} \
- void load() override { \
- Map::load(); \
- warning("TODO: Map not implemented yet"); \
- } \
- }
-
-PLACEHOLDER(01, 1, "portsmit", 0xC03);
-PLACEHOLDER(02, 2, "algary", 0x203);
-PLACEHOLDER(03, 3, "dusk", 0x802);
-PLACEHOLDER(04, 4, "erliquin", 0x0B1A);
-PLACEHOLDER(05, 5, "cave1", 0x0A11);
-PLACEHOLDER(06, 6, "cave2", 0x1);
-PLACEHOLDER(07, 7, "cave3", 0xC01);
-PLACEHOLDER(08, 8, "cave4", 0x202);
-PLACEHOLDER(09, 9, "cave5", 0x5);
-PLACEHOLDER(10, 10, "cave6", 0x51B);
-PLACEHOLDER(11, 11, "cave7", 0x212);
-PLACEHOLDER(12, 12, "cave8", 0x601);
-PLACEHOLDER(13, 13, "cave9", 0xA00);
-PLACEHOLDER(14, 14, "areaa1", 0xF01);
-PLACEHOLDER(15, 15, "areaa2", 0x502);
-PLACEHOLDER(16, 16, "areaa3", 0xB02);
-PLACEHOLDER(17, 17, "areaa4", 0x103);
-PLACEHOLDER(18, 18, "areab1", 0xA00);
-PLACEHOLDER(19, 19, "areab2", 0x703);
-PLACEHOLDER(20, 20, "areab3", 0x101);
-PLACEHOLDER(21, 21, "areab4", 0xD03);
-PLACEHOLDER(22, 22, "areac1", 0x304);
-PLACEHOLDER(23, 23, "areac2", 0xA11);
-PLACEHOLDER(24, 24, "areac3", 0x904);
-PLACEHOLDER(25, 25, "areac4", 0xF04);
-PLACEHOLDER(26, 26, "aread1", 0x505);
-PLACEHOLDER(27, 27, "aread2", 0xB05);
-PLACEHOLDER(28, 28, "aread3", 0x106);
-PLACEHOLDER(29, 29, "aread4", 0x801);
-PLACEHOLDER(30, 30, "areae1", 0x112);
-PLACEHOLDER(31, 31, "areae2", 0x706);
-PLACEHOLDER(32, 32, "areae3", 0xB1A);
-PLACEHOLDER(33, 33, "areae4", 0x11B);
-PLACEHOLDER(34, 34, "doom", 0x706);
-PLACEHOLDER(35, 35, "blackrn", 0xF08);
-PLACEHOLDER(36, 36, "blackrs", 0x508);
-PLACEHOLDER(37, 37, "qvl1", 0xF03);
-PLACEHOLDER(38, 38, "qvl2", 0x703);
-PLACEHOLDER(39, 39, "rwl1", 0xF02);
-PLACEHOLDER(40, 40, "rwl2", 0x702);
-PLACEHOLDER(41, 41, "enf1", 0xF04);
-PLACEHOLDER(42, 42, "enf2", 0x704);
-PLACEHOLDER(43, 43, "whitew", 0xA11);
-PLACEHOLDER(44, 44, "dragad", 0x107);
-PLACEHOLDER(45, 45, "udrag1", 0xF05);
-PLACEHOLDER(46, 46, "udrag2", 0xA00);
-PLACEHOLDER(47, 47, "udrag3", 0x705);
-PLACEHOLDER(48, 48, "demon", 0x412);
-PLACEHOLDER(49, 49, "alamar", 0xB07);
-PLACEHOLDER(50, 50, "pp1", 0xF01);
-PLACEHOLDER(51, 51, "pp2", 0x701);
-PLACEHOLDER(52, 52, "pp3", 0xE00);
-PLACEHOLDER(53, 53, "pp4", 0x201);
-PLACEHOLDER(54, 54, "astral", 0xB1A);
-#undef PLACEHOLDER
-
static const byte LOOKUPS_START[4] = { 0, 0, 14, 34 };
static const byte COLOR_OFFSET[55] = {
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 6854df33861..c6cad6a2eb9 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -94,6 +94,60 @@ MODULE_OBJS := \
mm1/maps/maps.o \
mm1/maps/map.o \
mm1/maps/map00.o \
+ mm1/maps/map01.o \
+ mm1/maps/map02.o \
+ mm1/maps/map03.o \
+ mm1/maps/map04.o \
+ mm1/maps/map05.o \
+ mm1/maps/map06.o \
+ mm1/maps/map07.o \
+ mm1/maps/map08.o \
+ mm1/maps/map09.o \
+ mm1/maps/map10.o \
+ mm1/maps/map11.o \
+ mm1/maps/map12.o \
+ mm1/maps/map13.o \
+ mm1/maps/map14.o \
+ mm1/maps/map15.o \
+ mm1/maps/map16.o \
+ mm1/maps/map17.o \
+ mm1/maps/map18.o \
+ mm1/maps/map19.o \
+ mm1/maps/map20.o \
+ mm1/maps/map21.o \
+ mm1/maps/map22.o \
+ mm1/maps/map23.o \
+ mm1/maps/map24.o \
+ mm1/maps/map25.o \
+ mm1/maps/map26.o \
+ mm1/maps/map27.o \
+ mm1/maps/map28.o \
+ mm1/maps/map29.o \
+ mm1/maps/map30.o \
+ mm1/maps/map31.o \
+ mm1/maps/map32.o \
+ mm1/maps/map33.o \
+ mm1/maps/map34.o \
+ mm1/maps/map35.o \
+ mm1/maps/map36.o \
+ mm1/maps/map37.o \
+ mm1/maps/map38.o \
+ mm1/maps/map39.o \
+ mm1/maps/map40.o \
+ mm1/maps/map41.o \
+ mm1/maps/map42.o \
+ mm1/maps/map43.o \
+ mm1/maps/map44.o \
+ mm1/maps/map45.o \
+ mm1/maps/map46.o \
+ mm1/maps/map47.o \
+ mm1/maps/map48.o \
+ mm1/maps/map49.o \
+ mm1/maps/map50.o \
+ mm1/maps/map51.o \
+ mm1/maps/map52.o \
+ mm1/maps/map53.o \
+ mm1/maps/map54.o \
xeen/worldofxeen/clouds_cutscenes.o \
xeen/worldofxeen/darkside_cutscenes.o \
xeen/worldofxeen/worldofxeen_cutscenes.o \
Commit: 1c85a6e199acd21503a8f7905dfded1f8f5db49a
https://github.com/scummvm/scummvm/commit/1c85a6e199acd21503a8f7905dfded1f8f5db49a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Remove unneeded todos from map classes
Changed paths:
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map06.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map13.cpp
engines/mm/mm1/maps/map14.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map16.cpp
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map19.cpp
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map21.cpp
engines/mm/mm1/maps/map22.cpp
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/maps/map26.cpp
engines/mm/mm1/maps/map27.cpp
engines/mm/mm1/maps/map28.cpp
engines/mm/mm1/maps/map29.cpp
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/map31.cpp
engines/mm/mm1/maps/map32.cpp
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/map34.cpp
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map38.cpp
engines/mm/mm1/maps/map39.cpp
engines/mm/mm1/maps/map40.cpp
engines/mm/mm1/maps/map41.cpp
engines/mm/mm1/maps/map42.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map44.cpp
engines/mm/mm1/maps/map45.cpp
engines/mm/mm1/maps/map46.cpp
engines/mm/mm1/maps/map47.cpp
engines/mm/mm1/maps/map48.cpp
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map50.cpp
engines/mm/mm1/maps/map51.cpp
engines/mm/mm1/maps/map52.cpp
engines/mm/mm1/maps/map53.cpp
engines/mm/mm1/maps/map54.cpp
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 9cfb3eb5340..058fdb98115 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -43,7 +43,6 @@ void Map00::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index f1100542763..e572d7394b5 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -35,8 +35,7 @@ void Map01::special() {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+ if (g_maps->_forwardMask & _data[68 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,11 +43,10 @@ void Map01::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map01::special00() {
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index addeb197eac..12b8d46ba8c 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -36,7 +36,7 @@ void Map02::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 70bef628241..5b05cd489b7 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -36,7 +36,7 @@ void Map03::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 592c18e6628..3c1700ec6db 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -36,7 +36,7 @@ void Map04::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 662153a63d4..5e47d60f36c 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -36,7 +36,7 @@ void Map05::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
index fead3f5abb7..561cd487170 100644
--- a/engines/mm/mm1/maps/map06.cpp
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -36,7 +36,7 @@ void Map06::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 33f88ffd64e..87e04061a21 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -36,7 +36,7 @@ void Map07::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index f155bb6aa83..173dcda6d3e 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -36,7 +36,7 @@ void Map08::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index b9ed15777bf..1c585810ebc 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -36,7 +36,7 @@ void Map09::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index 82b7e70d603..27c4e047af2 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -36,7 +36,7 @@ void Map10::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 286753d971d..9c63ea690e5 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -36,7 +36,7 @@ void Map11::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index edfe06ea0c0..50fc9b4b126 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -36,7 +36,7 @@ void Map12::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map13.cpp b/engines/mm/mm1/maps/map13.cpp
index cf3895eec11..8b6f091233a 100644
--- a/engines/mm/mm1/maps/map13.cpp
+++ b/engines/mm/mm1/maps/map13.cpp
@@ -36,7 +36,7 @@ void Map13::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
index e9ff92c87ae..518edd7f3ae 100644
--- a/engines/mm/mm1/maps/map14.cpp
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -36,7 +36,7 @@ void Map14::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index 5539afc2dcc..d09f881fb33 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -36,7 +36,7 @@ void Map15::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map16.cpp b/engines/mm/mm1/maps/map16.cpp
index 3805235081c..ea28cd1a6a7 100644
--- a/engines/mm/mm1/maps/map16.cpp
+++ b/engines/mm/mm1/maps/map16.cpp
@@ -36,7 +36,7 @@ void Map16::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 5c741d37eab..a89fe80bea6 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -36,7 +36,7 @@ void Map17::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index 73ab0340c4b..8b091990976 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -36,7 +36,7 @@ void Map18::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map19.cpp b/engines/mm/mm1/maps/map19.cpp
index c2769c4ced6..f2a5a0abd72 100644
--- a/engines/mm/mm1/maps/map19.cpp
+++ b/engines/mm/mm1/maps/map19.cpp
@@ -36,7 +36,7 @@ void Map19::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index b7a10f477f1..fb33f0a57fb 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -36,7 +36,7 @@ void Map20::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map21.cpp b/engines/mm/mm1/maps/map21.cpp
index 58967765ad4..3cc811d87e1 100644
--- a/engines/mm/mm1/maps/map21.cpp
+++ b/engines/mm/mm1/maps/map21.cpp
@@ -36,7 +36,7 @@ void Map21::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map22.cpp b/engines/mm/mm1/maps/map22.cpp
index 9a19f480122..45a63b430b1 100644
--- a/engines/mm/mm1/maps/map22.cpp
+++ b/engines/mm/mm1/maps/map22.cpp
@@ -36,7 +36,7 @@ void Map22::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index d0ec8cf64ad..4dc833ff539 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -36,7 +36,7 @@ void Map23::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index 355e8b87777..1eb99e5b290 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -36,7 +36,7 @@ void Map24::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index 17c69e653b1..e3286035005 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -36,7 +36,7 @@ void Map25::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map26.cpp b/engines/mm/mm1/maps/map26.cpp
index a9425c0d96a..22bbb5a35a6 100644
--- a/engines/mm/mm1/maps/map26.cpp
+++ b/engines/mm/mm1/maps/map26.cpp
@@ -36,7 +36,7 @@ void Map26::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
index 0a9ab5c7bf2..fe3273b7e0d 100644
--- a/engines/mm/mm1/maps/map27.cpp
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -36,7 +36,7 @@ void Map27::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map28.cpp b/engines/mm/mm1/maps/map28.cpp
index 7787a062cc2..70494677a50 100644
--- a/engines/mm/mm1/maps/map28.cpp
+++ b/engines/mm/mm1/maps/map28.cpp
@@ -36,7 +36,7 @@ void Map28::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
index 12697e10412..19af3ca66eb 100644
--- a/engines/mm/mm1/maps/map29.cpp
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -36,7 +36,7 @@ void Map29::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index ebf3c050e67..5a6ebb6ccbc 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -36,7 +36,7 @@ void Map30::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map31.cpp b/engines/mm/mm1/maps/map31.cpp
index 427a65064d1..3620f439b50 100644
--- a/engines/mm/mm1/maps/map31.cpp
+++ b/engines/mm/mm1/maps/map31.cpp
@@ -36,7 +36,7 @@ void Map31::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map32.cpp b/engines/mm/mm1/maps/map32.cpp
index 9059c37c807..4b60e393a49 100644
--- a/engines/mm/mm1/maps/map32.cpp
+++ b/engines/mm/mm1/maps/map32.cpp
@@ -36,7 +36,7 @@ void Map32::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index d447458570e..8a0e72f4a56 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -36,7 +36,7 @@ void Map33::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map34.cpp b/engines/mm/mm1/maps/map34.cpp
index 736f357126f..da6367dfda9 100644
--- a/engines/mm/mm1/maps/map34.cpp
+++ b/engines/mm/mm1/maps/map34.cpp
@@ -36,7 +36,7 @@ void Map34::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 020ba2e4879..b70b70bc9e7 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -36,7 +36,7 @@ void Map35::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index fe5680044e5..49caf86a357 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -36,7 +36,7 @@ void Map36::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index 4da3ffc4366..59de3898795 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -36,7 +36,7 @@ void Map37::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map38.cpp b/engines/mm/mm1/maps/map38.cpp
index 2176d6a85e3..38144473fd6 100644
--- a/engines/mm/mm1/maps/map38.cpp
+++ b/engines/mm/mm1/maps/map38.cpp
@@ -36,7 +36,7 @@ void Map38::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map39.cpp b/engines/mm/mm1/maps/map39.cpp
index 2fad5186a05..e72f23631d0 100644
--- a/engines/mm/mm1/maps/map39.cpp
+++ b/engines/mm/mm1/maps/map39.cpp
@@ -36,7 +36,7 @@ void Map39::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map40.cpp b/engines/mm/mm1/maps/map40.cpp
index bdd1a922ea7..61bd81390aa 100644
--- a/engines/mm/mm1/maps/map40.cpp
+++ b/engines/mm/mm1/maps/map40.cpp
@@ -36,7 +36,7 @@ void Map40::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map41.cpp b/engines/mm/mm1/maps/map41.cpp
index f0aff9f6e0d..d8e69c3ba52 100644
--- a/engines/mm/mm1/maps/map41.cpp
+++ b/engines/mm/mm1/maps/map41.cpp
@@ -36,7 +36,7 @@ void Map41::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
index 1571af74ceb..3299ae75878 100644
--- a/engines/mm/mm1/maps/map42.cpp
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -36,7 +36,7 @@ void Map42::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 051b8e0694d..63bee303fdb 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -36,7 +36,7 @@ void Map43::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map44.cpp b/engines/mm/mm1/maps/map44.cpp
index b0b0847e813..8d0d0adb848 100644
--- a/engines/mm/mm1/maps/map44.cpp
+++ b/engines/mm/mm1/maps/map44.cpp
@@ -36,7 +36,7 @@ void Map44::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map45.cpp b/engines/mm/mm1/maps/map45.cpp
index 55542944f3d..e7efb276dae 100644
--- a/engines/mm/mm1/maps/map45.cpp
+++ b/engines/mm/mm1/maps/map45.cpp
@@ -36,7 +36,7 @@ void Map45::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map46.cpp b/engines/mm/mm1/maps/map46.cpp
index 202d96b192d..e6f3b2fe954 100644
--- a/engines/mm/mm1/maps/map46.cpp
+++ b/engines/mm/mm1/maps/map46.cpp
@@ -36,7 +36,7 @@ void Map46::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map47.cpp b/engines/mm/mm1/maps/map47.cpp
index 8247ab7c187..1c8dbadadd3 100644
--- a/engines/mm/mm1/maps/map47.cpp
+++ b/engines/mm/mm1/maps/map47.cpp
@@ -36,7 +36,7 @@ void Map47::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map48.cpp b/engines/mm/mm1/maps/map48.cpp
index b941a5e65b6..a34a6f2aceb 100644
--- a/engines/mm/mm1/maps/map48.cpp
+++ b/engines/mm/mm1/maps/map48.cpp
@@ -36,7 +36,7 @@ void Map48::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index 9e221c31591..f6bcc7f6444 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -36,7 +36,7 @@ void Map49::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map50.cpp b/engines/mm/mm1/maps/map50.cpp
index 785aed40645..33a2e106d81 100644
--- a/engines/mm/mm1/maps/map50.cpp
+++ b/engines/mm/mm1/maps/map50.cpp
@@ -36,7 +36,7 @@ void Map50::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map51.cpp b/engines/mm/mm1/maps/map51.cpp
index bccc0187968..40bd7c76704 100644
--- a/engines/mm/mm1/maps/map51.cpp
+++ b/engines/mm/mm1/maps/map51.cpp
@@ -36,7 +36,7 @@ void Map51::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map52.cpp b/engines/mm/mm1/maps/map52.cpp
index dfefb6d9594..b413d30ef5e 100644
--- a/engines/mm/mm1/maps/map52.cpp
+++ b/engines/mm/mm1/maps/map52.cpp
@@ -36,7 +36,7 @@ void Map52::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map53.cpp b/engines/mm/mm1/maps/map53.cpp
index 55680c8f79c..c4436a5be20 100644
--- a/engines/mm/mm1/maps/map53.cpp
+++ b/engines/mm/mm1/maps/map53.cpp
@@ -36,7 +36,7 @@ void Map53::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index ef231be56a4..bd5b86fa03c 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -36,7 +36,7 @@ void Map54::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
- // TODO: Some extra message code
+
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
Commit: 22199d754637dedcda1fcb6682ca1de9f0576dd0
https://github.com/scummvm/scummvm/commit/22199d754637dedcda1fcb6682ca1de9f0576dd0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Created town map base class
Changed paths:
A engines/mm/mm1/maps/map_town.cpp
A engines/mm/mm1/maps/map_town.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map00.h
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map01.h
engines/mm/mm1/maps/map02.h
engines/mm/mm1/maps/map03.h
engines/mm/mm1/maps/map04.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c07f1075462..b6391d500a6 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -837,3 +837,28 @@ maps:
trapdoor: "TRAP DOOR!"
levitate: ", LEVITATION SAVES YOU!"
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+
+ map01:
+ sign: "A SIGN ABOVE THE DOOR READS:\n"
+ blacksmith: """B. SMITH',27h,'S WORKSHOP"""
+ inn: """INN OF PORTSMITH"""
+ market: """MAID MARION'S MARKET"""
+ tavern: """ZORELDA'S WATERING HOLE"""
+ temple: """TEMPLE SUCCUBON"""
+ training: """AMAZONIA',27h,'S TRAINING"""
+
+ blacksmith_inside: """BUSILY FORGING A LONG SWORD,AN EXTREMELY\nBEAUTIFUL YOUNG GIRL SAYS WITH A\nSEDUCTIVE SMILE, ""CAN I HELP YOU (Y/N)?"""
+ inn_inside: "LARA, THE INKEEPERS VOLUPTUOUS\nDAUGHTER, ASKS IF YOU WILL BE SPENDING\nTHE NIGHT... SIGN IN (Y/N)?"
+ market_inside: "FROM BEHIND THE FRUIT STAND\nA SULTRY VOICE ASKS, ""SEE ANYTHING\nYOU LIKE (Y/N)?"""
+ tavern_inside: "STEP UP TO THE BAR (Y/N)?"
+ temple_inside: "THE ONCE MAGNIFICENT TEMPLE SHOWS\nSIGNS OF NEGLECT AND DECAY. THE HIGH\nPRIESTESS ASKS,""NEED HELP (Y/N)?"""
+ training_inside: "A TALL, MUSCULAR FEMALE CLAD IN LEATHER\nARMOR APPROACHES ASKING, ""STRANGERS,\nARE YOU HERE FOR TRAINING (Y/N)?"""
+
+ males_drained: "MALES ARE DRAINED!"
+ passage_outside: "PASSAGE OUTSIDE, EXIT (Y/N)?"
+ secret: "A SENSUOUS FEMALE VOICE SPEAKS FROM\nWITHIN AN INTOXICATING MIST,\n""YOU'VE DISCOVERED MY SECRET!"""
+ stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
+ zam0: "NOTE: ZAM 12,2"
+ zam1: """I AM ZAM, ASTRAL BROTHER OF ZOM AND\nONLY LIVING MALE RESIDING IN PORTSMITH\n"
+ zam2: "MY CLUE IS C-15"""
+ zam3: "YOU'RE NOT THE COURIERS!"""
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index e12e1059f34..f8a31ea241f 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -63,6 +63,11 @@ enum Resistance {
RESISTANCE_PSYCHIC = 7
};
+enum CharFlags {
+ CHARFLAG_COURIER = 4,
+ CHARFLAG_ZAM_CLUE = 0x10
+};
+
class Inventory {
public:
struct Entry {
@@ -262,6 +267,7 @@ struct Character {
int _v6c, _v6e, _alignmentCtr;
byte _quest = 0;
+ byte _flags = 0;
// Non persistent fields
byte _numDrinks = 0;
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 058fdb98115..c483691f02c 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -57,13 +57,7 @@ void Map00::special() {
}
void Map00::special00() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
- STRING["maps.map00.inn_inside"],
- []() {
- g_events->replaceView("Inn");
- }
- ));
+ inn();
}
void Map00::special01() {
@@ -92,23 +86,11 @@ void Map00::special01() {
}
void Map00::special02() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
- STRING["maps.map00.blacksmith_inside"],
- []() {
- g_events->addView("Blacksmith");
- }
- ));
+ blacksmith();
}
void Map00::special03() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
- STRING["maps.map00.market_inside"],
- []() {
- g_events->addView("Market");
- }
- ));
+ market();
}
void Map00::special04() {
@@ -123,33 +105,15 @@ void Map00::special04() {
}
void Map00::special05() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
- STRING["maps.map00.tavern_inside"],
- []() {
- g_events->addView("Tavern");
- }
- ));
+ tavern();
}
void Map00::special06() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
- STRING["maps.map00.temple_inside"],
- []() {
- g_events->addView("Temple");
- }
- ));
+ temple();
}
void Map00::special07() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
- STRING["maps.map00.training_inside"],
- []() {
- g_events->addView("Training");
- }
- ));
+ trainer();
}
void Map00::special08() {
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index 04c465f211d..e41e9c057ce 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -22,13 +22,13 @@
#ifndef MM1_MAPS_MAP00_H
#define MM1_MAPS_MAP00_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_town.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map00 : public Map {
+class Map00 : public MapTown {
typedef void (Map00:: *SpecialFn)();
private:
void searchStatue();
@@ -85,7 +85,7 @@ private:
&Map00::special23
};
public:
- Map00() : Map(0, "sorpigal", 0x604) {}
+ Map00() : MapTown(0, "sorpigal", 0x604) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index e572d7394b5..44e21cd5c09 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -31,7 +31,7 @@ namespace Maps {
void Map01::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 17; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
@@ -50,6 +50,90 @@ void Map01::special() {
}
void Map01::special00() {
+ inn();
+}
+
+void Map01::special01() {
+ Common::String line1 = STRING["maps.map01.zam1"];
+ Common::String line2 = STRING["maps.map01.zam3"];
+
+ bool hasCourier = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
+ hasCourier = (g_globals->_party[i]._flags & CHARFLAG_COURIER) != 0;
+ }
+
+ if (hasCourier) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags |= CHARFLAG_COURIER | CHARFLAG_ZAM_CLUE;
+ }
+
+ line2 = STRING["maps.map01.zam2"];
+ }
+
+ send(InfoMessage(
+ 0, 1, line1,
+ 0, 3, line2
+ ));
+}
+
+void Map01::special02() {
+ blacksmith();
+}
+
+void Map01::special03() {
+ market();
+}
+
+void Map01::special04() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map01.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(3, 3);
+ g_maps->changeMap(0x101, 2);
+ }
+ ));
+
+}
+
+void Map01::special05() {
+ tavern();
+}
+
+void Map01::special06() {
+ temple();
+}
+
+void Map01::special07() {
+ trainer();
+}
+
+void Map01::special08() {
+}
+
+void Map01::special09() {
+}
+
+void Map01::special10() {
+}
+
+void Map01::special11() {
+}
+
+void Map01::special12() {
+}
+
+void Map01::special13() {
+}
+
+void Map01::special14() {
+}
+
+void Map01::special15() {
+}
+
+void Map01::special16() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map01.h b/engines/mm/mm1/maps/map01.h
index a28edf92391..d9b3a93b883 100644
--- a/engines/mm/mm1/maps/map01.h
+++ b/engines/mm/mm1/maps/map01.h
@@ -22,22 +22,54 @@
#ifndef MM1_MAPS_MAP01_H
#define MM1_MAPS_MAP01_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_town.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map01 : public Map {
+class Map01 : public MapTown {
typedef void (Map01:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
- const SpecialFn SPECIAL_FN[1] = {
- &Map01::special00
+ const SpecialFn SPECIAL_FN[17] = {
+ &Map01::special00,
+ &Map01::special01,
+ &Map01::special02,
+ &Map01::special03,
+ &Map01::special04,
+ &Map01::special05,
+ &Map01::special06,
+ &Map01::special07,
+ &Map01::special08,
+ &Map01::special09,
+ &Map01::special10,
+ &Map01::special11,
+ &Map01::special12,
+ &Map01::special13,
+ &Map01::special14,
+ &Map01::special15,
+ &Map01::special16
};
public:
- Map01() : Map(1, "portsmit", 0xC03) {}
+ Map01() : MapTown(1, "portsmit", 0xC03) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map02.h b/engines/mm/mm1/maps/map02.h
index 69fe6a90441..0fb3e4ba824 100644
--- a/engines/mm/mm1/maps/map02.h
+++ b/engines/mm/mm1/maps/map02.h
@@ -22,13 +22,13 @@
#ifndef MM1_MAPS_MAP02_H
#define MM1_MAPS_MAP02_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_town.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map02 : public Map {
+class Map02 : public MapTown {
typedef void (Map02:: *SpecialFn)();
private:
void special00();
@@ -37,7 +37,7 @@ private:
&Map02::special00
};
public:
- Map02() : Map(2, "algary", 0x203) {}
+ Map02() : MapTown(2, "algary", 0x203) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map03.h b/engines/mm/mm1/maps/map03.h
index 8ece67d6093..642035e2873 100644
--- a/engines/mm/mm1/maps/map03.h
+++ b/engines/mm/mm1/maps/map03.h
@@ -22,13 +22,13 @@
#ifndef MM1_MAPS_MAP03_H
#define MM1_MAPS_MAP03_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_town.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map03 : public Map {
+class Map03 : public MapTown {
typedef void (Map03:: *SpecialFn)();
private:
void special00();
@@ -37,7 +37,7 @@ private:
&Map03::special00
};
public:
- Map03() : Map(3, "dusk", 0x802) {}
+ Map03() : MapTown(3, "dusk", 0x802) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map04.h b/engines/mm/mm1/maps/map04.h
index 2a8c49e0cf3..0454c4f65ad 100644
--- a/engines/mm/mm1/maps/map04.h
+++ b/engines/mm/mm1/maps/map04.h
@@ -22,13 +22,13 @@
#ifndef MM1_MAPS_MAP04_H
#define MM1_MAPS_MAP04_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_town.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map04 : public Map {
+class Map04 : public MapTown {
typedef void (Map04:: *SpecialFn)();
private:
void special00();
@@ -37,7 +37,7 @@ private:
&Map04::special00
};
public:
- Map04() : Map(4, "erliquin", 0x0B1A) {}
+ Map04() : MapTown(4, "erliquin", 0x0B1A) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
new file mode 100644
index 00000000000..95a29fb0c9d
--- /dev/null
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -0,0 +1,94 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map_town.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void MapTown::blacksmith() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING[Common::String::format("maps.map%.2u.blacksmith_inside", _mapIndex)],
+ []() {
+ g_events->addView("Blacksmith");
+ }
+ ));
+}
+
+void MapTown::inn() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING[Common::String::format("maps.map%.2u.inn_inside", _mapIndex)],
+ []() {
+ g_events->replaceView("Inn");
+ }
+ ));
+}
+
+void MapTown::market() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING[Common::String::format("maps.map%.2u.market_inside", _mapIndex)],
+ []() {
+ g_events->addView("Market");
+ }
+ ));
+}
+
+void MapTown::tavern() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING[Common::String::format("maps.map%.2u.tavern_inside", _mapIndex)],
+ []() {
+ g_events->addView("Tavern");
+ }
+ ));
+}
+
+void MapTown::temple() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING[Common::String::format("maps.map%.2u.temple_inside", _mapIndex)],
+ []() {
+ g_events->addView("Temple");
+ }
+ ));
+}
+
+void MapTown::trainer() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING[Common::String::format("maps.map%.2u.training_inside", _mapIndex)],
+ []() {
+ g_events->addView("Training");
+ }
+ ));
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map_town.h b/engines/mm/mm1/maps/map_town.h
new file mode 100644
index 00000000000..eec1ba725ff
--- /dev/null
+++ b/engines/mm/mm1/maps/map_town.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP_TOWN_H
+#define MM1_MAPS_MAP_TOWN_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class MapTown : public Map {
+protected:
+ /**
+ * Handles visiting blacksmith
+ */
+ void blacksmith();
+
+ /**
+ * Handles visiting inn
+ */
+ void inn();
+
+ /**
+ * Handles visiting market
+ */
+ void market();
+
+ /**
+ * Handles visiting tavern
+ */
+ void tavern();
+
+ /**
+ * Handles visiting temple
+ */
+ void temple();
+
+ /**
+ * Handles visiting trainer
+ */
+ void trainer();
+
+public:
+ MapTown(uint index, const Common::String &name, uint16 id) :
+ Map(index, name, id) {}
+ virtual ~MapTown() {}
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c6cad6a2eb9..e3898143fbb 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -93,6 +93,7 @@ MODULE_OBJS := \
mm1/views_enh/locations/temple.o \
mm1/maps/maps.o \
mm1/maps/map.o \
+ mm1/maps/map_town.o \
mm1/maps/map00.o \
mm1/maps/map01.o \
mm1/maps/map02.o \
Commit: 9221ad76e5aed58c0968498d5ea2de9a4f17ec5b
https://github.com/scummvm/scummvm/commit/9221ad76e5aed58c0968498d5ea2de9a4f17ec5b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Map 1 has the first custom encounter
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map01.cpp
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 32628df10a1..c80f2de9a0e 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -171,8 +171,17 @@ void Character::synchronize(Common::Serializer &s) {
_equipped.synchronize(s, false);
_backpack.synchronize(s, false);
+ _physicalAttr.synchronize(s);
+ _missileAttr.synchronize(s);
+
+ s.syncAsByte(_v6c);
+ s.syncAsByte(_quest);
+ s.syncAsByte(_v6e);
+ s.syncAsByte(_alignmentCtr);
+ s.syncBytes(_flags, 8);
+
// TODO: Figure purpose of remaining unknown fields
- s.skip(39);
+ s.skip(7);
}
void Character::clear() {
@@ -206,6 +215,8 @@ void Character::clear() {
_resistances._s._poison.clear();
_resistances._s._psychic.clear();
_v6c = _alignmentCtr = 0;
+
+ Common::fill(&_flags[0], &_flags[8], 0);
}
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index f8a31ea241f..bec693b9847 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -63,9 +63,9 @@ enum Resistance {
RESISTANCE_PSYCHIC = 7
};
-enum CharFlags {
- CHARFLAG_COURIER = 4,
- CHARFLAG_ZAM_CLUE = 0x10
+enum CharFlags0 {
+ CHARFLAG0_COURIER = 4,
+ CHARFLAG0_ZAM_CLUE = 0x10
};
class Inventory {
@@ -264,10 +264,11 @@ struct Character {
// TODO: Figure out what these are
AttributePair _physicalAttr, _missileAttr;
- int _v6c, _v6e, _alignmentCtr;
-
+ int _v6c;
byte _quest = 0;
- byte _flags = 0;
+ int _v6e;
+ int _alignmentCtr;
+ byte _flags[8];
// Non persistent fields
byte _numDrinks = 0;
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 6c3bb4aa316..be3250c28e6 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -165,6 +165,16 @@ void Encounter::changeCharAlignment(Alignment align) {
}
}
+void Encounter::clearMonsters() {
+ _monsterList.size();
+}
+
+void Encounter::addMonster(byte id, byte arr1) {
+ const Monster &mons = g_globals->_monsters[id];
+ _monsterList.push_back(mons);
+ _arr1[_monsterList.size() - 1] = arr1;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 0676e245fd4..187d86d8d13 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -39,8 +39,7 @@ enum EncounterType {
class Encounter : public GameLogic {
private:
- bool _flag = false;
- int _levelIndex = 0, _levelOffset = 0;
+ int _levelOffset = 0;
int _val9 = 0;
int _monsterNum16 = 0;
int _totalLevels = 0;
@@ -59,6 +58,8 @@ public:
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
byte _arr1[MAX_COMBAT_MONSTERS];
+ bool _flag = false;
+ int _levelIndex = 0;
public:
/**
@@ -72,6 +73,16 @@ public:
bool checkSurroundParty() const;
void changeCharAlignment(Alignment align);
+
+ /**
+ * Clears the monster list
+ */
+ void clearMonsters();
+
+ /**
+ * Adds a monster to the monster list
+ */
+ void addMonster(byte id, byte arr1);
};
} // namespace Game
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 77b894ed952..fec5064c4bd 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -25,6 +25,7 @@
#include "common/array.h"
#include "common/str.h"
#include "mm/mm1/events.h"
+#include "mm/mm1/game/game_logic.h"
namespace MM {
namespace MM1 {
@@ -91,7 +92,7 @@ enum CellState {
class Maps;
-class Map {
+class Map : public Game::GameLogic {
protected:
Common::String _name;
uint16 _id;
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index 44e21cd5c09..3be4505ab11 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -59,13 +59,13 @@ void Map01::special01() {
bool hasCourier = false;
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
- hasCourier = (g_globals->_party[i]._flags & CHARFLAG_COURIER) != 0;
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER) != 0;
}
if (hasCourier) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._flags |= CHARFLAG_COURIER | CHARFLAG_ZAM_CLUE;
+ c._flags[0] |= CHARFLAG0_COURIER | CHARFLAG0_ZAM_CLUE;
}
line2 = STRING["maps.map01.zam2"];
@@ -94,7 +94,6 @@ void Map01::special04() {
g_maps->changeMap(0x101, 2);
}
));
-
}
void Map01::special05() {
@@ -110,6 +109,34 @@ void Map01::special07() {
}
void Map01::special08() {
+ // Paralyze all the men
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c._sex == MALE && !(c._condition & BAD_CONDITION))
+ c._condition = PARALYZED;
+ }
+
+ // Redraw the party
+ g_events->send("GameParty", GameMessage("UPDATE"));
+
+ // Show the message and wait for a keypress
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map01.secret"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ enc.clearMonsters();
+
+ uint count = getRandomNumber(4) + 4;
+ enc.addMonster(6, 12);
+ for (uint i = 0; i < count; ++i)
+ enc.addMonster(4, 9);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
+ ));
}
void Map01::special09() {
Commit: ddf7ca4f56d327cfc5fb4f13eed4b8b6e661012c
https://github.com/scummvm/scummvm/commit/ddf7ca4f56d327cfc5fb4f13eed4b8b6e661012c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Fix loading character roster
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index c80f2de9a0e..1bffd84d0c5 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -35,6 +35,11 @@ Resistances::Resistances() {
_arr[i].clear();
}
+void Resistances::synchronize(Common::Serializer &s) {
+ for (int i = 0; i < 8; ++i)
+ _arr[i].synchronize(s);
+}
+
void Inventory::clear() {
_items.clear();
_items.resize(INVENTORY_COUNT);
@@ -171,6 +176,7 @@ void Character::synchronize(Common::Serializer &s) {
_equipped.synchronize(s, false);
_backpack.synchronize(s, false);
+ _resistances.synchronize(s);
_physicalAttr.synchronize(s);
_missileAttr.synchronize(s);
@@ -178,10 +184,9 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_quest);
s.syncAsByte(_v6e);
s.syncAsByte(_alignmentCtr);
- s.syncBytes(_flags, 8);
+ s.syncBytes(_flags, 14);
- // TODO: Figure purpose of remaining unknown fields
- s.skip(7);
+ s.skip(1);
}
void Character::clear() {
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index bec693b9847..e87a1b034de 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -228,6 +228,11 @@ union Resistances {
AttributePair _arr[8];
Resistances();
+
+ /**
+ * Handles save/loading resistences
+ */
+ void synchronize(Common::Serializer &s);
};
struct Character {
@@ -268,7 +273,7 @@ struct Character {
byte _quest = 0;
int _v6e;
int _alignmentCtr;
- byte _flags[8];
+ byte _flags[14];
// Non persistent fields
byte _numDrinks = 0;
Commit: 4f4130774b1bc3ad68ea22bc74d8af514aafb348
https://github.com/scummvm/scummvm/commit/4f4130774b1bc3ad68ea22bc74d8af514aafb348
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Remainder of map 1 logic
Changed paths:
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map01.h
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index 3be4505ab11..a033d98cb6a 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -49,6 +49,14 @@ void Map01::special() {
g_globals->_encounters.execute();
}
+void Map01::showSign(const Common::String &msg) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 2, 1, STRING["maps.map00.sign"],
+ 6, 2, msg
+ ));
+}
+
void Map01::special00() {
inn();
}
@@ -140,27 +148,47 @@ void Map01::special08() {
}
void Map01::special09() {
+ Sound::sound(SOUND_2);
+
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map01.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(8, 0);
+ g_maps->changeMap(0xc01, 1);
+ }
+ ));
}
void Map01::special10() {
+ showSign(STRING["maps.map01.market"]);
}
void Map01::special11() {
+ showSign(STRING["maps.map01.blacksmith"]);
}
void Map01::special12() {
+ showSign(STRING["maps.map01.inn"]);
}
void Map01::special13() {
+ showSign(STRING["maps.map01.temple"]);
}
void Map01::special14() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 0, 1, STRING["maps.map00.zam0"]
+ ));
}
void Map01::special15() {
+ showSign(STRING["maps.map01.tavern"]);
}
void Map01::special16() {
+ showSign(STRING["maps.map01.training"]);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map01.h b/engines/mm/mm1/maps/map01.h
index d9b3a93b883..93db1a4f67a 100644
--- a/engines/mm/mm1/maps/map01.h
+++ b/engines/mm/mm1/maps/map01.h
@@ -49,6 +49,8 @@ private:
void special15();
void special16();
+ void showSign(const Common::String &msg);
+
const SpecialFn SPECIAL_FN[17] = {
&Map01::special00,
&Map01::special01,
Commit: dd423c184b8284cbfcfb5eb84c1d461e6af1deb9
https://github.com/scummvm/scummvm/commit/dd423c184b8284cbfcfb5eb84c1d461e6af1deb9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Add virtual destructors to base classes
Changed paths:
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.h
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 401e086c4ca..190bd5b944c 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -84,6 +84,14 @@ protected:
*/
Combat();
+ /**
+ * Destructor
+ */
+ virtual ~Combat() {}
+
+ /**
+ * Sets the combat display mode
+ */
virtual void setMode(Mode newMode) = 0;
/**
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index c2555ceec7f..339af7cd87e 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -187,6 +187,7 @@ protected:
public:
SpellsMonsters();
+ virtual ~SpellsMonsters() {}
/**
* Monster casts a spell
Commit: 53ae2cf0703f0c2ea5bf451eb2369fe7a4849fe1
https://github.com/scummvm/scummvm/commit/53ae2cf0703f0c2ea5bf451eb2369fe7a4849fe1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:18+01:00
Commit Message:
MM: MM1: Add dumping of item list and loading from engine data
Changed paths:
A devtools/create_mm/files/mm1/items.txt
A engines/mm/mm1/data/text_parser.cpp
A engines/mm/mm1/data/text_parser.h
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/items.cpp
engines/mm/mm1/data/items.h
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
engines/mm/mm1/views/locations/blacksmith_subview.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/spells/recharge_item.cpp
engines/mm/mm1/views_enh/locations/temple.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/items.txt b/devtools/create_mm/files/mm1/items.txt
new file mode 100644
index 00000000000..674f6412be7
--- /dev/null
+++ b/devtools/create_mm/files/mm1/items.txt
@@ -0,0 +1,256 @@
+"CLUB ", 0, 0, 0, 0, 0, 0, 1, 3, 0
+"DAGGER ", 4, 0, 0, 0, 0, 0, 5, 4, 0
+"HAND AXE ", 6, 0, 0, 0, 0, 0, 10, 5, 0
+"SPEAR ", 7, 0, 0, 0, 0, 0, 15, 6, 0
+"SHORT SWORD ", 6, 0, 0, 0, 0, 0, 20, 6, 0
+"MACE ", 2, 0, 0, 0, 0, 0, 40, 6, 0
+"FLAIL ", 2, 0, 0, 0, 0, 0, 40, 7, 0
+"SCIMITAR ", 6, 0, 0, 0, 0, 0, 40, 7, 0
+"BROAD SWORD ", 6, 0, 0, 0, 0, 0, 50, 7, 0
+"BATTLE AXE ", 6, 0, 0, 0, 0, 0, 60, 0, 0
+"LONG SWORD ", 6, 0, 0, 0, 0, 0, 60, 8, 0
+"CLUB +1 ", 0, 0, 0, 0, 0, 0, 30, 3, 1
+"CLUB +2 ", 0, 0, 0, 0, 0, 0, 100, 3, 2
+"DAGGER +1 ", 4, 0, 0, 0, 0, 0, 50, 4, 1
+"HAND AXE +1 ", 134, 33, 1, 0, 0, 0, 75, 5, 1
+"SPEAR +1 ", 71, 33, 1, 0, 0, 0, 100, 6, 1
+"SHORT SWORD +1", 6, 0, 0, 0, 0, 0, 100, 6, 1
+"MACE +1 ", 2, 0, 0, 0, 0, 0, 125, 6, 1
+"FLAIL +1 ", 2, 0, 0, 0, 0, 0, 200, 7, 1
+"SCIMITAR +1 ", 70, 33, 2, 0, 0, 0, 250, 7, 1
+"BROAD SWORD +1", 134, 33, 2, 0, 0, 0, 300, 7, 1
+"BATTLE AXE +1 ", 6, 0, 0, 0, 0, 0, 300, 8, 1
+"LONG SWORD +1 ", 6, 0, 0, 0, 0, 0, 300, 8, 1
+"FLAMING CLUB ", 0, 90, 20, 255, 50, 30, 500, 3, 3
+"CLUB OF NOISE ", 0, 255, 0, 0, 0, 0, 100, 3, 0
+"DAGGER +2 ", 4, 0, 0, 255, 52, 25, 200, 4, 2
+"HAND AXE +2 ", 70, 33, 2, 0, 0, 0, 225, 5, 2
+"SPEAR +2 ", 135, 33, 2, 0, 0, 0, 250, 6, 2
+"SHORT SWORD +2", 6, 0, 0, 255, 48, 15, 300, 6, 2
+"MACE +2 ", 2, 25, 1, 255, 7, 10, 325, 6, 2
+"FLAIL +2 ", 2, 25, 1, 255, 3, 15, 350, 7, 2
+"SCIMITAR +2 ", 134, 23, 1, 0, 0, 0, 400, 7, 2
+"BROAD SWORD +2", 70, 23, 1, 0, 0, 0, 400, 7, 2
+"BATTLE AXE +2 ", 6, 90, 20, 24, 2, 10, 500, 8, 2
+"LONG SWORD +2 ", 6, 96, 20, 24, 2, 10, 550, 8, 2
+"ROYAL DAGGER ", 196, 0, 0, 0, 0, 0, 2500, 4, 0
+"DAGGER OF MIND", 61, 21, 3, 255, 77, 20, 750, 4, 3
+"DIAMOND DAGGER", 61, 23, 4, 0, 0, 0, 800, 10, 4
+"ELECTRIC SPEAR", 7, 94, 40, 255, 55, 16, 1200, 6, 3
+"HOLY MACE ", 123, 25, 3, 255, 38, 5, 2000, 6, 4
+"UN-HOLY MACE ", 187, 25, 3, 255, 37, 5, 2000, 6, 4
+"DARK FLAIL ", 131, 255, 0, 255, 33, 10, 600, 3, 0
+"FLAIL OF FEAR ", 59, 98, 40, 255, 62, 8, 1600, 7, 3
+"LUCKY SCIMITAR", 6, 33, 5, 0, 0, 0, 2200, 7, 4
+"MACE OF UNDEAD", 67, 255, 0, 37, 10, 5, 500, 6, 0
+"COLD AXE ", 15, 92, 40, 255, 72, 10, 2500, 8, 3
+"ELECTRIC SWORD", 7, 94, 40, 255, 66, 10, 2200, 8, 3
+"FLAMING SWORD ", 7, 90, 50, 255, 63, 10, 2200, 8, 3
+"SWORD OF MIGHT", 31, 23, 6, 24, 5, 30, 8000, 8, 5
+"SWORD OF SPEED", 7, 29, 6, 30, 5, 20, 7000, 8, 5
+"SHARP SWORD ", 143, 88, 21, 255, 81, 5, 6500, 10, 4
+"ACCURATE SWORD", 71, 31, 6, 32, 5, 10, 6500, 8, 6
+"SWORD OF MAGIC", 6, 88, 30, 255, 87, 15, 10000, 8, 5
+"IMMORTAL SWORD", 70, 33, 5, 255, 39, 25, 7000, 8, 4
+"AXE PROTECTOR ", 7, 88, 25, 255, 92, 15, 8000, 8, 5
+"AXE DESTROYER ", 143, 23, 4, 255, 85, 6, 8000, 8, 5
+"X!XX!X'S SWORD", 198, 33, 15, 34, 5, 10, 6000, 8, 4
+"ADAMANTINE AXE", 7, 33, 8, 255, 36, 5, 12000, 8, 5
+"ULTIMATE SWORD", 6, 23, 10, 30, 5, 20, 15000, 20, 6
+"ELEMENT SWORD ", 6, 88, 25, 255, 44, 10, 12000, 8, 5
+"SLING ", 6, 0, 0, 0, 0, 0, 10, 4, 0
+"CROSSBOW ", 6, 0, 0, 0, 0, 0, 50, 6, 0
+"SHORT BOW ", 7, 0, 0, 0, 0, 0, 75, 8, 0
+"LONG BOW ", 7, 0, 0, 0, 0, 0, 100, 10, 0
+"GREAT BOW ", 7, 0, 0, 0, 0, 0, 250, 12, 0
+"SLING +1 ", 6, 0, 0, 0, 0, 0, 50, 4, 1
+"CROSSBOW +1 ", 6, 0, 0, 0, 0, 0, 250, 6, 1
+"SHORT BOW +1 ", 7, 0, 0, 0, 0, 0, 375, 8, 1
+"LONG BOW +1 ", 7, 0, 0, 0, 0, 0, 500, 10, 1
+"GREAT BOW +1 ", 7, 0, 0, 0, 0, 0, 1250, 12, 1
+"MAGIC SLING ", 6, 88, 10, 89, 20, 10, 800, 4, 3
+"CROSSBOW +2 ", 54, 31, 2, 0, 0, 0, 1000, 6, 2
+"SHORT BOW +2 ", 135, 102, 10, 0, 0, 0, 1000, 8, 2
+"LONG BOW +2 ", 71, 102, 10, 0, 0, 0, 1200, 10, 2
+"GREAT BOW +2 ", 7, 98, 30, 0, 0, 0, 2000, 12, 2
+"CROSSBOW LUCK ", 54, 33, 3, 255, 1, 20, 2000, 6, 3
+"CROSSBOW SPEED", 6, 29, 4, 255, 2, 10, 2000, 6, 3
+"LIGHTNING BOW ", 71, 94, 20, 255, 63, 10, 3000, 10, 3
+"FLAMING BOW ", 135, 90, 20, 255, 66, 10, 3000, 10, 3
+"GIANT'S BOW ", 7, 0, 0, 0, 0, 0, 2000, 20, 3
+"THE MAGIC BOW ", 71, 88, 20, 255, 83, 5, 6000, 16, 4
+"BOW OF POWER ", 135, 98, 40, 36, 4, 15, 6000, 16, 4
+"ROBBER'S X-BOW", 62, 29, 4, 255, 61, 10, 8000, 10, 5
+"ARCHER'S BOW ", 55, 31, 5, 255, 85, 10, 12000, 20, 5
+"OBSIDIAN BOW ", 0, 255, 0, 255, 80, 3, 2000, 3, 0
+" ", 0, 0, 0, 0, 0, 0, 0, 0, 0
+"STAFF ", 1, 0, 0, 0, 0, 0, 30, 8, 0
+"GLAIVE ", 7, 0, 0, 0, 0, 0, 80, 10, 0
+"BARDICHE ", 7, 0, 0, 0, 0, 0, 80, 10, 0
+"HALBERD ", 7, 0, 0, 0, 0, 0, 100, 12, 0
+"GREAT HAMMER ", 3, 0, 0, 0, 0, 0, 150, 12, 0
+"GREAT AXE ", 7, 0, 0, 0, 0, 0, 150, 12, 0
+"FLAMBERGE ", 7, 0, 0, 0, 0, 0, 250, 14, 0
+"STAFF +1 ", 1, 21, 1, 0, 0, 0, 200, 8, 1
+"GLAIVE +1 ", 135, 29, 1, 0, 0, 0, 350, 10, 1
+"BARDICHE +1 ", 71, 29, 1, 0, 0, 0, 350, 10, 1
+"HALBERD +1 ", 7, 0, 0, 0, 0, 0, 500, 12, 1
+"GREAT HAMMER+1", 3, 25, 1, 0, 0, 0, 550, 12, 1
+"GREAT AXE +1 ", 7, 0, 0, 0, 0, 0, 500, 12, 1
+"FLAMBERGE +1 ", 7, 0, 0, 0, 0, 0, 600, 14, 1
+"STAFF +2 ", 1, 33, 2, 255, 54, 10, 600, 8, 2
+"GLAIVE +2 ", 135, 29, 2, 0, 0, 0, 900, 10, 2
+"BARDICHE +2 ", 71, 29, 2, 0, 0, 0, 900, 10, 2
+"HALBERD +2 ", 7, 29, 3, 255, 3, 20, 1200, 12, 2
+"GREAT HAMMER+2", 3, 25, 2, 255, 1, 20, 1200, 12, 2
+"GREAT AXE +2 ", 7, 23, 2, 24, 2, 10, 1200, 12, 2
+"FLAMBERGE +2 ", 7, 23, 2, 24, 2, 10, 2000, 14, 2
+"STAFF OF LIGHT", 1, 102, 40, 255, 19, 20, 1500, 8, 3
+"COLD GLAIVE ", 135, 92, 40, 255, 21, 20, 2500, 10, 3
+"CURING STAFF ", 121, 100, 30, 255, 5, 12, 2500, 8, 3
+"MINOTAUR'S AXE", 7, 255, 0, 0, 0, 0, 2000, 3, 0
+"THUNDER HAMMER", 59, 94, 40, 255, 29, 15, 3500, 12, 4
+"GREAT AXE +3 ", 7, 23, 4, 30, 3, 10, 3500, 12, 3
+"FLAMBERGE +3 ", 7, 23, 4, 30, 3, 10, 5000, 14, 3
+"SORCERER STAFF", 61, 21, 4, 255, 91, 10, 8000, 8, 5
+"STAFF OF MAGIC", 1, 88, 25, 255, 87, 10, 5000, 8, 4
+"DEMON'S GLAIVE", 215, 96, 50, 255, 71, 40, 10000, 10, 5
+"DEVIL'S GLAIVE", 215, 92, 50, 255, 72, 40, 10000, 10, 5
+"THE FLAMBERGE ", 7, 23, 10, 255, 73, 10, 15000, 30, 6
+"HOLY FLAMBERGE", 111, 88, 50, 255, 43, 15, 20000, 20, 6
+"EVIL FLAMBERGE", 175, 88, 50, 255, 46, 15, 20000, 20, 6
+"PADDED ARMOR ", 0, 0, 0, 0, 0, 0, 10, 0, 1
+"LEATHER ARMOR ", 2, 0, 0, 0, 0, 0, 20, 0, 2
+"SCALE ARMOR ", 2, 0, 0, 0, 0, 0, 50, 0, 3
+"RING MAIL ", 2, 0, 0, 0, 0, 0, 100, 0, 4
+"CHAIN MAIL ", 3, 0, 0, 0, 0, 0, 200, 0, 5
+"SPLINT MAIL ", 15, 0, 0, 0, 0, 0, 400, 0, 6
+"PLATE MAIL ", 15, 0, 0, 0, 0, 0, 1000, 0, 7
+"PADDED +1 ", 0, 0, 0, 0, 0, 0, 25, 0, 2
+"LEATHER +1 ", 2, 0, 0, 0, 0, 0, 60, 0, 3
+"SCALE +1 ", 2, 0, 0, 0, 0, 0, 120, 0, 4
+"RING MAIL +1 ", 2, 90, 5, 0, 0, 0, 250, 0, 5
+"CHAIN MAIL +1 ", 3, 90, 5, 0, 0, 0, 500, 0, 6
+"SPLINT MAIL +1", 15, 90, 10, 0, 0, 0, 1000, 0, 7
+"PLATE MAIL +1 ", 15, 90, 10, 0, 0, 0, 2500, 0, 8
+"LEATHER +2 ", 2, 94, 10, 0, 0, 0, 150, 0, 4
+"SCALE +2 ", 2, 92, 10, 0, 0, 0, 300, 0, 5
+"RING MAIL +2 ", 2, 90, 15, 0, 0, 0, 750, 0, 6
+"CHAIN MAIL +2 ", 3, 90, 15, 0, 0, 0, 1500, 0, 7
+"SPLINT MAIL +2", 15, 90, 20, 0, 0, 0, 2500, 0, 8
+"PLATE MAIL +2 ", 15, 90, 20, 0, 0, 0, 7500, 0, 9
+"BRACERS AC 4 ", 52, 0, 0, 0, 0, 0, 1000, 0, 4
+"RING MAIL +3 ", 2, 29, 2, 0, 0, 0, 2000, 0, 7
+"CHAIN MAIL +3 ", 3, 33, 4, 0, 0, 0, 4500, 0, 8
+"SPLINT MAIL +3", 15, 23, 2, 0, 0, 0, 7500, 0, 9
+"PLATE MAIL +3 ", 15, 90, 50, 0, 0, 0, 15000, 0, 10
+"BRACERS AC 6 ", 52, 98, 20, 255, 77, 20, 2500, 0, 6
+"CHAIN MAIL +3 ", 3, 255, 0, 0, 0, 0, 4500, 0, 0
+"BRACERS AC 8 ", 0, 255, 0, 0, 0, 0, 7500, 0, 0
+"BLUE RING MAIL", 2, 94, 60, 255, 66, 30, 10000, 0, 9
+"RED CHAIN MAIL", 3, 90, 60, 255, 63, 30, 15000, 0, 10
+"X!XX!X'S PLATE", 207, 33, 10, 34, 5, 10, 18000, 0, 11
+"HOLY PLATE ", 111, 88, 40, 99, 50, 30, 25000, 0, 12
+"UN-HOLY PLATE ", 175, 88, 40, 99, 50, 30, 25000, 0, 12
+"ULTIMATE PLATE", 21, 88, 40, 255, 49, 30, 30000, 0, 13
+"BRACERS AC 8 ", 52, 98, 60, 255, 77, 40, 7500, 0, 8
+"SMALL SHIELD ", 10, 0, 0, 0, 0, 0, 10, 0, 1
+"LARGE SHIELD ", 10, 0, 0, 0, 0, 0, 50, 0, 2
+"SILVER SHIELD ", 10, 102, 20, 0, 0, 0, 100, 0, 2
+"SMALL SHIELD+1", 10, 0, 0, 0, 0, 0, 100, 0, 2
+"LARGE SHIELD+1", 10, 0, 0, 0, 0, 0, 200, 0, 3
+"LARGE SHIELD+1", 10, 255, 0, 0, 0, 0, 200, 0, 0
+"SMALL SHIELD+2", 10, 0, 0, 0, 0, 0, 400, 0, 3
+"LARGE SHIELD+2", 10, 0, 0, 0, 0, 0, 800, 0, 4
+"LARGE SHIELD+2", 10, 255, 0, 0, 0, 0, 800, 0, 0
+"FIRE SHIELD ", 10, 90, 20, 0, 0, 0, 2500, 0, 5
+"COLD SHIELD ", 10, 92, 20, 0, 0, 0, 2500, 0, 5
+"ELEC SHIELD ", 10, 94, 20, 0, 0, 0, 2500, 0, 5
+"ACID SHIELD ", 10, 96, 20, 0, 0, 0, 2500, 0, 5
+"MAGIC SHIELD ", 10, 88, 20, 255, 77, 20, 5000, 0, 6
+"DRAGON SHIELD ", 10, 88, 10, 255, 92, 20, 8000, 0, 7
+"ROPE & HOOKS ", 0, 1, 0, 255, 58, 30, 10, 0, 0
+"TORCH ", 0, 1, 0, 255, 4, 1, 2, 0, 0
+"LANTERN ", 0, 1, 0, 255, 4, 10, 20, 0, 0
+"10 FOOT POLE ", 0, 1, 0, 0, 0, 0, 10, 0, 0
+"GARLIC ", 0, 1, 0, 0, 0, 0, 5, 0, 0
+"WOLFSBANE ", 0, 1, 0, 0, 0, 0, 10, 0, 0
+"BELLADONNA ", 0, 1, 0, 0, 0, 0, 25, 0, 0
+"MAGIC HERBS ", 0, 1, 0, 255, 3, 3, 50, 0, 0
+"DRIED BEEF ", 0, 1, 0, 62, 6, 3, 40, 0, 0
+"ROBBER'S TOOLS", 62, 108, 20, 0, 0, 0, 150, 0, 0
+"BAG OF SILVER ", 0, 1, 0, 0, 0, 0, 300, 0, 0
+"AMBER GEM ", 0, 1, 0, 0, 0, 0, 500, 0, 0
+"SMELLING SALT ", 0, 1, 0, 255, 0, 3, 50, 0, 0
+"BAG OF SAND ", 0, 1, 0, 255, 54, 5, 100, 0, 0
+"MIGHT POTION ", 0, 1, 0, 24, 5, 3, 200, 0, 0
+"SPEED POTION ", 0, 1, 0, 30, 5, 3, 200, 0, 0
+"SUNDIAL ", 0, 1, 0, 255, 53, 50, 500, 0, 0
+"CURING POTION ", 0, 1, 0, 255, 8, 4, 350, 0, 0
+"MAGIC POTION ", 0, 1, 0, 43, 10, 2, 500, 0, 0
+"DEFENSE RING ", 0, 60, 1, 255, 57, 30, 500, 0, 0
+"BAG OF GARBAGE", 0, 255, 0, 0, 0, 0, 100, 0, 0
+"SCROLL OF FIRE", 0, 1, 0, 255, 63, 1, 300, 0, 0
+"FLYING CARPET ", 61, 60, 2, 255, 64, 10, 500, 0, 0
+"JADE AMULET ", 255, 19, 5, 0, 0, 0, 600, 0, 0
+"ANTIDOTE BREW ", 0, 1, 0, 255, 25, 2, 500, 0, 0
+"SKILL POTION ", 0, 1, 0, 36, 5, 5, 600, 0, 0
+"BOOTS OF SPEED", 0, 29, 5, 30, 10, 10, 800, 0, 0
+"LUCKY CHARM ", 0, 33, 5, 34, 10, 20, 800, 0, 0
+"WAND OF FIRE ", 53, 90, 15, 255, 63, 10, 1000, 0, 0
+"UNDEAD AMULET ", 0, 98, 50, 255, 7, 20, 800, 0, 0
+"SILENT CHIME ", 0, 1, 0, 255, 14, 20, 400, 0, 0
+"BELT OF POWER ", 14, 23, 5, 0, 0, 0, 600, 0, 0
+"MODEL BOAT ", 0, 1, 0, 255, 23, 15, 400, 0, 0
+"DEFENSE CLOAK ", 0, 60, 2, 0, 0, 0, 700, 0, 0
+"KNOWLEDGE BOOK", 33, 21, 2, 48, 1, 4, 1000, 0, 0
+"RUBY IDOL ", 0, 1, 0, 0, 0, 0, 3000, 0, 0
+"SORCERER ROBE ", 61, 21, 5, 255, 65, 20, 2500, 0, 0
+"POWER GAUNTLET", 2, 23, 5, 0, 0, 0, 3000, 0, 0
+"CLERIC'S BEADS", 59, 25, 5, 255, 8, 50, 3000, 0, 0
+"HORN OF DEATH ", 0, 1, 0, 255, 81, 10, 2500, 0, 0
+"POTION OF LIFE", 0, 1, 0, 255, 38, 2, 1500, 0, 0
+"SHINY PENDANT ", 0, 102, 30, 255, 56, 10, 2000, 0, 0
+"LIGHTNING WAND", 50, 94, 20, 255, 66, 10, 1500, 0, 0
+"PRECISION RING", 0, 31, 5, 0, 0, 0, 3000, 0, 0
+"RETURN SCROLL ", 0, 1, 0, 255, 41, 1, 2000, 0, 0
+"TELEPORT HELM ", 0, 88, 10, 255, 83, 20, 5000, 0, 0
+"YOUTH POTION ", 0, 1, 0, 255, 39, 2, 4000, 0, 0
+"BELLS OF TIME ", 0, 1, 0, 37, 10, 50, 1000, 0, 0
+"MAGIC OIL ", 0, 1, 0, 255, 88, 1, 3000, 0, 0
+"MAGIC VEST ", 0, 88, 20, 255, 78, 10, 6000, 0, 0
+"DESTROYER WAND", 53, 88, 10, 255, 85, 10, 7000, 0, 0
+"ELEMENT SCARAB", 0, 25, 5, 255, 44, 20, 6000, 0, 0
+"SUN SCROLL ", 0, 1, 0, 255, 46, 1, 3000, 0, 0
+"STAR RUBY ", 0, 33, 10, 255, 49, 30, 6000, 0, 0
+"STAR SAPPHIRE ", 0, 88, 30, 255, 87, 10, 6000, 0, 0
+"WEALTH CHEST ", 0, 1, 0, 58, 20, 5, 6000, 0, 0
+"GEM SACK ", 0, 1, 0, 49, 10, 10, 10000, 0, 0
+"DIAMOND COLLAR", 0, 37, 80, 255, 93, 10, 10000, 0, 0
+"FIRE OPAL ", 0, 37, 80, 255, 91, 10, 10000, 0, 0
+"UNOBTAINIUM ", 255, 16, 5, 0, 0, 0, 50000, 0, 0
+"VELLUM SCROLL ", 0, 1, 0, 0, 0, 0, 10, 0, 0
+"RUBY WHISTLE ", 0, 33, 2, 255, 0, 200, 500, 0, 0
+"KINGS PASS ", 0, 1, 0, 0, 0, 0, 0, 0, 0
+"MERCHANTS PASS", 0, 1, 0, 0, 0, 0, 0, 0, 0
+"CRYSTAL KEY ", 0, 1, 0, 255, 93, 10, 1000, 0, 0
+"CORAL KEY ", 0, 1, 0, 255, 23, 10, 300, 0, 0
+"BRONZE KEY ", 0, 1, 0, 255, 48, 20, 500, 0, 0
+"SILVER KEY ", 0, 1, 0, 255, 51, 30, 600, 0, 0
+"GOLD KEY ", 0, 1, 0, 255, 65, 15, 800, 0, 0
+"DIAMOND KEY ", 0, 1, 0, 255, 83, 20, 2000, 0, 0
+"CACTUS NECTAR ", 0, 1, 0, 255, 16, 10, 400, 0, 0
+"MAP OF DESERT ", 0, 1, 0, 255, 53, 20, 400, 0, 0
+"LASER BLASTER ", 0, 31, 5, 255, 85, 10, 2000, 0, 0
+"DRAGONS TOOTH ", 0, 1, 0, 255, 39, 10, 1500, 0, 0
+"WYVERN EYE ", 0, 1, 0, 255, 62, 20, 1000, 0, 0
+"MEDUSA HEAD ", 0, 255, 0, 0, 0, 0, 0, 0, 0
+"RING OF OKRIM ", 0, 33, 10, 255, 78, 20, 3000, 0, 0
+"B QUEEN IDOL ", 0, 1, 0, 0, 0, 0, 0, 0, 0
+"W QUEEN IDOL ", 0, 1, 0, 0, 0, 0, 0, 0, 0
+"PIRATES MAP A ", 0, 1, 0, 0, 0, 0, 1000, 0, 0
+"PIRATES MAP B ", 0, 1, 0, 0, 0, 0, 2000, 0, 0
+"THUNDRANIUM ", 0, 1, 0, 24, 15, 250, 10000, 0, 0
+"KEY CARD ", 0, 1, 0, 0, 0, 0, 0, 0, 0
+"EYE OF GOROS ", 0, 1, 0, 255, 89, 20, 10000, 0, 0
+"(USELESS ITEM)", 0, 1, 0, 0, 0, 0, 0, 0, 0
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 9461a892aed..9ecadd88359 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -34,6 +34,7 @@ namespace MM1 {
Console::Console() : GUI::Debugger() {
registerCmd("dump_map", WRAP_METHOD(Console, cmdDumpMap));
registerCmd("dump_monsters", WRAP_METHOD(Console, cmdDumpMonsters));
+ registerCmd("dump_items", WRAP_METHOD(Console, cmdDumpItems));
registerCmd("map_string", WRAP_METHOD(Console, cmdMapString));
registerCmd("map", WRAP_METHOD(Console, cmdMap));
registerCmd("pos", WRAP_METHOD(Console, cmdPos));
@@ -149,6 +150,49 @@ bool Console::cmdDumpMonsters(int argc, const char **argv) {
return true;
}
+bool Console::cmdDumpItems(int argc, const char **argv) {
+ Common::File f;
+ Common::DumpFile df;
+ Common::String line;
+
+ if (f.open("mm.exe")) {
+ if (df.open("items.txt")) {
+ f.seek(0x19b2a);
+
+ for (int i = 0; i < 255; ++i) {
+ if (i == 85) {
+ // Add the blank unused item line
+ line = "\" \", 0, 0, 0, 0, 0, 0, 0, 0, 0";
+ df.writeString(line);
+ df.writeByte('\n');
+ }
+
+ line = "\"";
+ for (int j = 0; j < 14; ++j)
+ line += f.readByte();
+ line += '"';
+
+ for (int j = 0; j < 9; ++j) {
+ line += ", ";
+ line += Common::String::format("%d",
+ (j == 6) ? f.readUint16BE() : f.readByte());
+ }
+
+ df.writeString(line);
+ df.writeByte('\n');
+ }
+
+ df.close();
+ f.close();
+ debugPrintf("Done\n");
+ return true;
+ }
+ }
+
+ debugPrintf("Could not create\n");
+ return true;
+}
+
bool Console::cmdMapString(int argc, const char **argv) {
Common::File f;
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index deddb8486cf..115b37b9fb6 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -40,6 +40,11 @@ protected:
*/
bool cmdDumpMonsters(int argc, const char **argv);
+ /**
+ * Dumps the item list
+ */
+ bool cmdDumpItems(int argc, const char **argv);
+
/**
* Prints a string from within a map's data segment
*/
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 1bffd84d0c5..d83145199d7 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -328,7 +328,7 @@ Character::LevelIncrease Character::increaseLevel() {
}
Character::BuyResult Character::buyItem(byte itemId) {
- getItem(itemId);
+ g_globals->_items.getItem(itemId);
// Check if backpack is full
int slotIndex = 0;
diff --git a/engines/mm/mm1/data/items.cpp b/engines/mm/mm1/data/items.cpp
index 527dc591cf5..bdd50db3991 100644
--- a/engines/mm/mm1/data/items.cpp
+++ b/engines/mm/mm1/data/items.cpp
@@ -25,103 +25,36 @@
namespace MM {
namespace MM1 {
-// TODO: Figure out all item fields
-const ItemData ITEMS1[86] = {
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 },
- { 0 }
-};
+bool ItemsArray::load() {
+ Common::File f;
+ if (!f.open("items.txt"))
+ return false;
-const ItemData ITEMS2[] = {
- { 0 }
-};
+ resize(256);
+ for (int lineNum = 0; lineNum < 256; ++lineNum) {
+ Item &item = (*this)[lineNum];
+ Common::String line = f.readLine();
+ assert(line.size() > 20 && line[0] == '"' && line[15] == '"');
-Item *getItem(byte index) {
- g_globals->_currItem = (index >= 86) ?
- ITEMS1[index - 1] : ITEMS2[index - 86];
+ item._name = Common::String(line.c_str() + 1, line.c_str() + 14);
+ line = Common::String(line.c_str() + 16);
+
+ item._disablements = getNextValue(line);
+ item._equipMode = (EquipMode)getNextValue(line);
+ item._val10 = getNextValue(line);
+ item._effectId = getNextValue(line);
+ item._spellId = getNextValue(line);
+ item._maxCharges = getNextValue(line);
+ item._cost = getNextValue(line);
+ item._val16 = getNextValue(line);
+ item._val17 = getNextValue(line);
+ }
+
+ return true;
+}
+
+Item *ItemsArray::getItem(byte index) const {
+ g_globals->_currItem = (*this)[index];
g_globals->_currItem._name = STRING[Common::String::format(
"stats.items.%d", (int)index)];
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index e5f19a73bd9..a795ac4fb84 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -22,7 +22,9 @@
#ifndef MM1_DATA_ITEMS_H
#define MM1_DATA_ITEMS_H
-#include "common/str.h"
+#include "common/array.h"
+#include "common/stream.h"
+#include "mm/mm1/data/text_parser.h"
namespace MM {
namespace MM1 {
@@ -52,30 +54,34 @@ enum TransferKind {
struct ItemData {
- byte _disablements;
- EquipMode _equipMode;
- byte _val10;
- byte _effectId;
- byte _spellId;
- byte _maxCharges;
- uint16 _cost;
- byte _val16;
- byte _val17;
+ byte _disablements = 0;
+ EquipMode _equipMode = EQUIPMODE_0;
+ byte _val10 = 0;
+ byte _effectId = 0;
+ byte _spellId = 0;
+ byte _maxCharges = 0;
+ uint16 _cost = 0;
+ byte _val16 = 0;
+ byte _val17 = 0;
};
struct Item : public ItemData {
Common::String _name;
-
- Item *operator=(const ItemData &rhs) {
- *dynamic_cast<ItemData *>(this) = rhs;
- _name.clear();
- return this;
- }
};
-extern const ItemData ITEMS1[];
-extern const ItemData ITEMS2[];
+struct ItemsArray : public Common::Array<Item>, public TextParser {
+ ItemsArray() {}
+
+ /**
+ * Loads the items array
+ */
+ bool load();
+ /**
+ * Gets an item
+ */
+ Item *getItem(byte index) const;
+};
inline bool isWeapon(byte id) {
return id >= 1 && id <= 60;
@@ -93,7 +99,6 @@ inline bool isShield(byte id) {
return id >= 156 && id <= 170;
};
-extern Item *getItem(byte index);
extern ItemCategory getItemCategory(byte itemId);
} // namespace MM1
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 4aa24ee2192..c75e1cf8aee 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -61,21 +61,6 @@ bool Monsters::load() {
return true;
}
-uint Monsters::getNextValue(Common::String &line) {
- // Verify the next comma
- if (!line.hasPrefix(", "))
- return 0;
- line.deleteChar(0);
- line.deleteChar(0);
-
- // Get the value
- int result = atoi(line.c_str());
- while (!line.empty() && Common::isDigit(line.firstChar()))
- line.deleteChar(0);
-
- return result;
-}
-
Graphics::ManagedSurface Monsters::getMonsterImage(int monsterNum) {
Common::SeekableReadStream *entry = _monPix.load(monsterNum);
entry->skip(2);
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 51f74585235..b5d02eb6d85 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -23,6 +23,7 @@
#define MM1_DATA_MONSTERS_H
#include "mm/mm1/gfx/dta.h"
+#include "mm/mm1/data/text_parser.h"
#include "common/str.h"
#include "graphics/managed_surface.h"
@@ -72,15 +73,10 @@ struct Monster {
byte _field1f;
};
-class Monsters {
+class Monsters : public TextParser {
private:
Monster _monsters[MONSTERS_COUNT];
Gfx::DTA _monPix;
-private:
- /**
- * Get the next value from a read line
- */
- uint getNextValue(Common::String &line);
public:
Monsters() : _monPix(MONPIX_DTA) {}
diff --git a/engines/mm/mm1/data/text_parser.cpp b/engines/mm/mm1/data/text_parser.cpp
new file mode 100644
index 00000000000..7db522dc3bb
--- /dev/null
+++ b/engines/mm/mm1/data/text_parser.cpp
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/text_parser.h"
+#include "common/util.h"
+
+namespace MM {
+namespace MM1 {
+
+uint TextParser::getNextValue(Common::String &line) {
+ // Verify the next comma
+ if (!line.hasPrefix(", "))
+ return 0;
+ line.deleteChar(0);
+ line.deleteChar(0);
+
+ // Get the value
+ int result = atoi(line.c_str());
+ while (!line.empty() && Common::isDigit(line.firstChar()))
+ line.deleteChar(0);
+
+ return result;
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/text_parser.h b/engines/mm/mm1/data/text_parser.h
new file mode 100644
index 00000000000..86e61d9279b
--- /dev/null
+++ b/engines/mm/mm1/data/text_parser.h
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_TEXT_PARSER_H
+#define MM1_DATA_TEXT_PARSER_H
+
+#include "common/str.h"
+
+namespace MM {
+namespace MM1 {
+
+/**
+ * Get the next value from a read line
+ */
+struct TextParser {
+ static uint getNextValue(Common::String &line);
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 03a7f5a0a32..f4bbccec6a3 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -53,7 +53,7 @@ bool Globals::load(bool isEnhanced) {
if (!_font.load("font.bmp"))
return false;
- if (!_monsters.load())
+ if (!_monsters.load() || !_items.load())
return false;
// Load roster
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index e183bd7396e..1fa4ac4c75e 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -43,6 +43,7 @@ public:
Roster _roster;
Character *_currCharacter = nullptr;
Item _currItem;
+ ItemsArray _items;
Maps::TownId _startingTown = Maps::SORPIGAL;
Maps::Maps _maps;
bool _intangible = false; // Console flag
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 1326a67e24f..707f10a1cf3 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -323,7 +323,7 @@ void CharacterInfo::equipItem(uint index) {
break;
}
- getItem(itemId);
+ g_globals->_items.getItem(itemId);
const Item &item = g_globals->_currItem;
if (equipError.empty() && (item._disablements & classBit))
@@ -451,7 +451,7 @@ void CharacterInfo::removeItem(uint index) {
Common::String removeError;
- getItem(itemId);
+ g_globals->_items.getItem(itemId);
const Item &item = g_globals->_currItem;
if (item._equipMode == EQUIP_CURSED) {
removeError = STRING["dialogs.character.cursed"];
@@ -570,7 +570,7 @@ void CharacterInfo::tradeHowMuch() {
}
void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
- Item *item = getItem(invEntry._id);
+ Item *item = g_globals->_items.getItem(invEntry._id);
Common::String msg;
if (!item->_effectId) {
@@ -612,7 +612,7 @@ void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
}
void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
- Item *item = getItem(invEntry._id);
+ Item *item = g_globals->_items.getItem(invEntry._id);
Common::String msg;
if (!item->_effectId) {
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index 7e41e89c80c..b6cec655900 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -69,7 +69,7 @@ void BlacksmithSellItem::selectItem(uint index) {
int v14 = c._backpack[index]._charges;
c._backpack.removeAt(index);
- getItem(itemId);
+ g_globals->_items.getItem(itemId);
if (!v14 && g_globals->_currItem._maxCharges)
g_globals->_currItem._cost /= 2;
diff --git a/engines/mm/mm1/views/locations/blacksmith_subview.cpp b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
index 2186cb6c87a..c3f12dcc01d 100644
--- a/engines/mm/mm1/views/locations/blacksmith_subview.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
@@ -35,7 +35,7 @@ void BlacksmithSubview::drawItems() {
writeChar(17, 1, 'A' + idx);
writeString(") ");
- getItem(_items[idx]);
+ g_globals->_items.getItem(_items[idx]);
drawIsAllowed();
writeString(g_globals->_currItem._name);
_textPos.x = 35;
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 32c295bd024..d0235f28e2e 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -106,7 +106,7 @@ void Temple::changeCharacter(uint index) {
_uncurseCost = UNCURSE_COST[townNum];
for (i = 0; i < INVENTORY_COUNT; ++i) {
if (c._equipped[i]) {
- if (getItem(c._equipped[i])->_equipMode == EQUIP_CURSED)
+ if (g_globals->_items.getItem(c._equipped[i])->_equipMode == EQUIP_CURSED)
break;
}
}
@@ -171,7 +171,7 @@ void Temple::uncurseItems() {
Character &c = *g_globals->_currCharacter;
for (int i = 0; i < INVENTORY_COUNT; ++i) {
if (c._equipped[i]) {
- getItem(c._equipped[i]);
+ g_globals->_items.getItem(c._equipped[i]);
if (g_globals->_currItem._equipMode == EQUIP_CURSED) {
c._equipped.removeAt(i);
--i;
diff --git a/engines/mm/mm1/views/spells/recharge_item.cpp b/engines/mm/mm1/views/spells/recharge_item.cpp
index d9d1fce90bb..70976a88944 100644
--- a/engines/mm/mm1/views/spells/recharge_item.cpp
+++ b/engines/mm/mm1/views/spells/recharge_item.cpp
@@ -55,7 +55,7 @@ bool RechargeItem::msgKeypress(const KeypressMessage &msg) {
} else if (msg.keycode >= Common::KEYCODE_a &&
msg.keycode < (Common::KEYCODE_a + (int)inv.size())) {
int itemIndex = msg.keycode - Common::KEYCODE_a;
- Item *item = getItem(inv[itemIndex]._id);
+ Item *item = g_globals->_items.getItem(inv[itemIndex]._id);
if (g_engine->getRandomNumber(100) == 100) {
// OMG: The original seriously had this fringe
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
index ae3fa859976..b6c725aad9a 100644
--- a/engines/mm/mm1/views_enh/locations/temple.cpp
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -141,7 +141,7 @@ void Temple::changeCharacter(uint index) {
_uncurseCost = UNCURSE_COST[townNum];
for (i = 0; i < INVENTORY_COUNT; ++i) {
if (c._equipped[i]) {
- if (getItem(c._equipped[i])->_equipMode == EQUIP_CURSED)
+ if (g_globals->_items.getItem(c._equipped[i])->_equipMode == EQUIP_CURSED)
break;
}
}
@@ -175,7 +175,7 @@ void Temple::uncurseItems() {
Character &c = *g_globals->_currCharacter;
for (int i = 0; i < INVENTORY_COUNT; ++i) {
if (c._equipped[i]) {
- getItem(c._equipped[i]);
+ g_globals->_items.getItem(c._equipped[i]);
if (g_globals->_currItem._equipMode == EQUIP_CURSED) {
c._equipped.removeAt(i);
--i;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index e3898143fbb..5e31acda4b5 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -22,6 +22,7 @@ MODULE_OBJS := \
mm1/data/monsters.o \
mm1/data/party.o \
mm1/data/roster.o \
+ mm1/data/text_parser.o \
mm1/game/game_logic.o \
mm1/game/combat.o \
mm1/game/encounter.o \
Commit: a8ad015fbec3f0ca2277ba522de8353f8477eedd
https://github.com/scummvm/scummvm/commit/a8ad015fbec3f0ca2277ba522de8353f8477eedd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: Add missing breaks to switch statement
Changed paths:
engines/mm/mm1/game/spell_casting.cpp
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 0fc87b4dca8..d5fabe1c03c 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -138,14 +138,19 @@ Common::String SpellCasting::getSpellError() const {
switch (_spellState) {
case SS_NOT_ENOUGH_SP:
msg = STRING["spells.not_enough_sp"];
+ break;
case SS_NOT_ENOUGH_GEMS:
msg = STRING["spells.not_enough_gems"];
+ break;
case SS_COMBAT_ONLY:
msg = STRING["spells.combat_only"];
+ break;
case SS_OUTDOORS_ONLY:
msg = STRING["spells.outdoors_only"];
+ break;
default:
msg = STRING["spells.done"];
+ break;
}
if (!g_globals->_inCombat)
Commit: 6ef8d409faa78314206ade7ac041f48094292d4b
https://github.com/scummvm/scummvm/commit/6ef8d409faa78314206ade7ac041f48094292d4b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: Add missing file to module.mk
Changed paths:
engines/mm/module.mk
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 5e31acda4b5..efc87c9ea91 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -83,6 +83,7 @@ MODULE_OBJS := \
mm1/views_enh/character_info.o \
mm1/views_enh/dialogs.o \
mm1/views_enh/game.o \
+ mm1/views_enh/game_commands.o \
mm1/views_enh/game_messages.o \
mm1/views_enh/map.o \
mm1/views_enh/scroll_popup.o \
Commit: 0a00d9878a4ce85623c7728f846b158ebb0dd85b
https://github.com/scummvm/scummvm/commit/0a00d9878a4ce85623c7728f846b158ebb0dd85b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: Fix movement
Changed paths:
engines/mm/mm1/meta_engine.cpp
diff --git a/engines/mm/mm1/meta_engine.cpp b/engines/mm/mm1/meta_engine.cpp
index da7f69839cd..bdf1b9fa430 100644
--- a/engines/mm/mm1/meta_engine.cpp
+++ b/engines/mm/mm1/meta_engine.cpp
@@ -125,8 +125,8 @@ static const KeysRecord NORMAL_RECORDS[] = {
static const KeysRecord *MODE_RECORDS[5] = {
MENU_RECORDS,
PARTY_MENU_RECORDS,
- COMBAT_MENU_RECORDS,
NORMAL_RECORDS,
+ COMBAT_MENU_RECORDS,
nullptr // TODO: combat keybindings
};
Commit: 81496fa2b0133a01962e31bd2e71b807ae3d3ba4
https://github.com/scummvm/scummvm/commit/81496fa2b0133a01962e31bd2e71b807ae3d3ba4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: Implemented most of map 2
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map01.h
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map02.h
engines/mm/mm1/maps/map_town.cpp
engines/mm/mm1/maps/map_town.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b6391d500a6..124f59c2692 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -862,3 +862,31 @@ maps:
zam1: """I AM ZAM, ASTRAL BROTHER OF ZOM AND\nONLY LIVING MALE RESIDING IN PORTSMITH\n"
zam2: "MY CLUE IS C-15"""
zam3: "YOU'RE NOT THE COURIERS!"""
+
+ map02:
+ sign: "A SIGN ABOVE THE DOOR READS:\n"
+ blacksmith: """SWAMPSIDE SUPPLIES"""
+ inn: """THE INN OF ALGARY"""
+ market: """ARCON'S SLOP"""
+ tavern: """JOLLY JESTER TAVERN"""
+ temple: """TEMPLE HALF-DEAD"""
+ training: """DRAGONS CLAW TRAINING"""
+ docks: """YE OLD DOCKS"""
+
+ blacksmith_inside: "A MAN ENCLOSED IN A STEEL CAGE SAYS,\n""CAN I HELP YOU FIND ANYTHING (Y/N)?"""
+ inn_inside: "STANDING BEHIND A LARGE DESK, A TALL\nBEARDED HALF-ORC GRUNTS, ""IF YOU DON'T\nSIGN IN, YOU CAN'T STAY! WELL (Y/N)?"""
+ market_inside: "A PUTRID SMELL PERVADES THE ROOM...\nLOOK FOR SOME FOOD (Y/N)?"
+ tavern_inside: "STEP UP TO THE BAR (Y/N)?"
+ temple_inside: "AN ANCIENT LOOKING CLERIC STAGGERS UP TOTHE PARTY GASPING, ""I CAN HELP,\nREALLY I CAN!"" ACCEPT THE OFFER (Y/N)?"
+ training_inside: "SEVERAL ADVENTURERS ARMORED IN DRAGON\nSCALES, ADDRESS THE PARTY,\n""LOOKING FOR TRAINING (Y/N)?"""
+
+ morango: "MORANGO THE MYSTIC ASKS,\n""WHO SHALL I MEASURE (1-6)?"""
+ passage_outside: "PASSAGE OUTSIDE, EXIT (Y/N)?"
+ resistances1: "% RESISTANCE FOR "
+ resistances2: "MAGIC FIRE COLD ELEC\nACID FEAR POISON SLEEP"
+ pit: "SWAZE PIT! JUMP IN (Y/N)?"
+ portal: "A MAGIC PORTAL! ENTER (Y/N)?"
+ zom0: "NOTE: ZOM 1,1"
+ zom1: """I AM ZOM, ASTRAL BROTHER OF ZAM.\n"
+ zom2: "MY CLUE IS 1-15."""
+ zom3: "YOU'RE NOT THE COURIERS!"""
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index e87a1b034de..5564f3e224f 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -65,6 +65,7 @@ enum Resistance {
enum CharFlags0 {
CHARFLAG0_COURIER = 4,
+ CHARFLAG0_ZOM_CLUE = 8,
CHARFLAG0_ZAM_CLUE = 0x10
};
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index a033d98cb6a..92265f9f85c 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -49,14 +49,6 @@ void Map01::special() {
g_globals->_encounters.execute();
}
-void Map01::showSign(const Common::String &msg) {
- Sound::sound(SOUND_2);
- send(InfoMessage(
- 2, 1, STRING["maps.map00.sign"],
- 6, 2, msg
- ));
-}
-
void Map01::special00() {
inn();
}
diff --git a/engines/mm/mm1/maps/map01.h b/engines/mm/mm1/maps/map01.h
index 93db1a4f67a..d9b3a93b883 100644
--- a/engines/mm/mm1/maps/map01.h
+++ b/engines/mm/mm1/maps/map01.h
@@ -49,8 +49,6 @@ private:
void special15();
void special16();
- void showSign(const Common::String &msg);
-
const SpecialFn SPECIAL_FN[17] = {
&Map01::special00,
&Map01::special01,
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 12b8d46ba8c..51349b7c795 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -29,13 +29,18 @@ namespace MM {
namespace MM1 {
namespace Maps {
+static const byte PORTAL_DEST_X[4] = { 8, 15, 0, 5 };
+static const byte PORTAL_DEST_Y[4] = { 4, 0, 0, 14 };
+static const uint16 PORTAL_DEST_ID[4] = { 0xc03, 0xa00, 0xf01, 0x604 };
+static const byte PORTAL_DEST_SECTION[4] = { 3, 0, 1, 4 };
+
void Map02::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 22; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[73 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +49,135 @@ void Map02::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map02::special00() {
+ inn();
+}
+
+void Map02::special01() {
+ Common::String line1 = STRING["maps.map02.zom1"];
+ Common::String line2 = STRING["maps.map02.zom3"];
+
+ bool hasCourier = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER) != 0;
+ }
+
+ if (hasCourier) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[0] |= CHARFLAG0_COURIER | CHARFLAG0_ZOM_CLUE;
+ }
+
+ line2 = STRING["maps.map02.zom2"];
+ }
+
+ send(InfoMessage(
+ 0, 1, line1,
+ 0, 3, line2
+ ));
+
+}
+
+void Map02::special02() {
+ blacksmith();
+}
+
+void Map02::special03() {
+ market();
+}
+
+void Map02::special04() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map02.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 7);
+ g_maps->changeMap(0x801, 2);
+ }
+ ));
+}
+
+void Map02::special05() {
+ tavern();
+}
+
+void Map02::special06() {
+ temple();
+}
+
+void Map02::special07() {
+ trainer();
+}
+
+void Map02::special08() {
+ // TODO: Show resistances
+
+}
+
+void Map02::special09() {
+ showSign(STRING["maps.map02.docks"]);
+}
+
+void Map02::special10() {
+ showSign(STRING["maps.map02.market"]);
+}
+
+void Map02::special11() {
+ showSign(STRING["maps.map02.blacksmith"]);
+}
+
+void Map02::special12() {
+ showSign(STRING["maps.map02.inn"]);
+}
+
+void Map02::special13() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map01.zom0"]));
+}
+
+void Map02::special14() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map02.pit"],
+ []() {
+ g_maps->_mapPos.x++;
+ g_globals->_encounters.execute();
+ }
+ ));
+}
+
+void Map02::special15() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map02.portal"],
+ []() {
+ int index = g_maps->_mapPos.x - 9;
+ g_maps->_mapPos.x = PORTAL_DEST_X[index];
+ g_maps->_mapPos.y = PORTAL_DEST_Y[index];
+
+ uint16 id = PORTAL_DEST_ID[index];
+ byte section = PORTAL_DEST_SECTION[index];
+ g_maps->changeMap(id, section);
+ }
+ ));
+}
+
+void Map02::special18() {
+ showSign(STRING["maps.map02.temple"]);
+}
+
+void Map02::special20() {
+ showSign(STRING["maps.map02.tavern"]);
+}
+
+void Map02::special21() {
+ showSign(STRING["maps.map02.training"]);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map02.h b/engines/mm/mm1/maps/map02.h
index 0fb3e4ba824..33ca57f6f55 100644
--- a/engines/mm/mm1/maps/map02.h
+++ b/engines/mm/mm1/maps/map02.h
@@ -32,9 +32,48 @@ class Map02 : public MapTown {
typedef void (Map02:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special18();
+ void special20();
+ void special21();
- const SpecialFn SPECIAL_FN[1] = {
- &Map02::special00
+ const SpecialFn SPECIAL_FN[22] = {
+ &Map02::special00,
+ &Map02::special01,
+ &Map02::special02,
+ &Map02::special03,
+ &Map02::special04,
+ &Map02::special05,
+ &Map02::special06,
+ &Map02::special07,
+ &Map02::special08,
+ &Map02::special09,
+ &Map02::special10,
+ &Map02::special11,
+ &Map02::special12,
+ &Map02::special13,
+ &Map02::special14,
+ &Map02::special15,
+ &Map02::special15,
+ &Map02::special15,
+ &Map02::special18,
+ &Map02::special15,
+ &Map02::special20,
+ &Map02::special21
};
public:
Map02() : MapTown(2, "algary", 0x203) {}
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
index 95a29fb0c9d..ceddb102930 100644
--- a/engines/mm/mm1/maps/map_town.cpp
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -89,6 +89,14 @@ void MapTown::trainer() {
));
}
+void MapTown::showSign(const Common::String &msg) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 2, 1, STRING[Common::String::format("maps.map%.2u.sign", _mapIndex)],
+ 6, 2, msg
+ ));
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map_town.h b/engines/mm/mm1/maps/map_town.h
index eec1ba725ff..ff4889cb40e 100644
--- a/engines/mm/mm1/maps/map_town.h
+++ b/engines/mm/mm1/maps/map_town.h
@@ -60,6 +60,10 @@ protected:
*/
void trainer();
+ /**
+ * Show a sign message
+ */
+ void showSign(const Common::String &msg);
public:
MapTown(uint index, const Common::String &name, uint16 id) :
Map(index, name, id) {}
Commit: 22c8e97787283f5642f858f7da0e52e12a8476b5
https://github.com/scummvm/scummvm/commit/22c8e97787283f5642f858f7da0e52e12a8476b5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: Implemented map 2 resistances display
Changed paths:
A engines/mm/mm1/views/maps/resistances.cpp
A engines/mm/mm1/views/maps/resistances.h
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 51349b7c795..4289e98aa3f 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -116,8 +116,7 @@ void Map02::special07() {
}
void Map02::special08() {
- // TODO: Show resistances
-
+ g_events->addView("Resistances");
}
void Map02::special09() {
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 11ef9de0947..2d7360bbf8a 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -43,6 +43,7 @@
#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
+#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/views/spells/detect_magic.h"
#include "mm/mm1/views/spells/duplication.h"
@@ -78,6 +79,8 @@ private:
Views::Locations::Temple _temple;
Views::Locations::Training _training;
+ Views::Maps::Resistances _resistances;
+
Views::Spells::CastSpell _castSpell;
Views::Spells::DetectMagic _detectMagicSpell;
Views::Spells::Duplication _duplicationSpell;
diff --git a/engines/mm/mm1/views/maps/resistances.cpp b/engines/mm/mm1/views/maps/resistances.cpp
new file mode 100644
index 00000000000..b4801423874
--- /dev/null
+++ b/engines/mm/mm1/views/maps/resistances.cpp
@@ -0,0 +1,105 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/resistances.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+Resistances::Resistances() : TextView("Resistances") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Resistances::msgFocus(const FocusMessage &msg) {
+ _charSelected = false;
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_PARTY_MENUS);
+ return TextView::msgFocus(msg);
+}
+
+bool Resistances::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return TextView::msgUnfocus(msg);
+}
+
+void Resistances::draw() {
+ clearSurface();
+ Sound::sound(SOUND_2);
+
+ if (!_charSelected) {
+ writeString(0, 1, STRING["maps.map02.morango"]);
+
+ } else {
+ Character &c = *g_globals->_currCharacter;
+ writeString(0, 1, STRING["maps.map02.resistances1"]);
+ writeString(c._name);
+ newLine();
+ writeString(0, 1, STRING["maps.map02.resistances2"]);
+
+ writeNumber(6, 1, c._resistances._s._magic);
+ writeNumber(15, 1, c._resistances._s._fire);
+ writeNumber(26, 1, c._resistances._s._cold);
+ writeNumber(36, 1, c._resistances._s._electricity);
+ writeNumber(6, 2, c._resistances._s._acid);
+ writeNumber(15, 2, c._resistances._s._fear);
+ writeNumber(26, 2, c._resistances._s._poison);
+ writeNumber(36, 2, c._resistances._s._psychic);
+ }
+}
+
+bool Resistances::msgKeypress(const KeypressMessage &msg) {
+ if (_charSelected)
+ close();
+ return true;
+}
+
+bool Resistances::msgMouseDown(const MouseDownMessage &msg) {
+ if (_charSelected)
+ close();
+ return true;
+}
+
+bool Resistances::msgAction(const ActionMessage &msg) {
+ if (msg._action == KEYBIND_ESCAPE) {
+ close();
+
+ } else if (!_charSelected &&
+ msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ uint charIndex = (int)(msg._action - KEYBIND_VIEW_PARTY1);
+ if (charIndex < g_globals->_party.size()) {
+ _charSelected = true;
+ g_globals->_currCharacter = &g_globals->_party[charIndex];
+ redraw();
+ }
+ }
+
+ return true;
+}
+
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/resistances.h b/engines/mm/mm1/views/maps/resistances.h
new file mode 100644
index 00000000000..0dbfb684db6
--- /dev/null
+++ b/engines/mm/mm1/views/maps/resistances.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_RESISTANCES_H
+#define MM1_VIEWS_MAPS_RESISTANCES_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Resistances : public TextView {
+private:
+ bool _charSelected = false;
+public:
+ Resistances();
+ virtual ~Resistances() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgMouseDown(const MouseDownMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index efc87c9ea91..94360e3cc90 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -50,6 +50,7 @@ MODULE_OBJS := \
mm1/views/locations/tavern.o \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
+ mm1/views/maps/resistances.o \
mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
mm1/views/spells/detect_magic.o \
Commit: faa8ae199101227a56b460415742709328e9876a
https://github.com/scummvm/scummvm/commit/faa8ae199101227a56b460415742709328e9876a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: Implemented map 3
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map03.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 124f59c2692..c287cf56ce7 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -890,3 +890,29 @@ maps:
zom1: """I AM ZOM, ASTRAL BROTHER OF ZAM.\n"
zom2: "MY CLUE IS 1-15."""
zom3: "YOU'RE NOT THE COURIERS!"""
+
+ map03:
+ sign: "A SIGN ABOVE THE DOOR READS:\n"
+ blacksmith: """MYSTICAL METAL WORKS"""
+ inn: """THE INN OF DUSK"""
+ market: """FEWLERD'S FEED"""
+ tavern: """CASPER'S FINE SPIRITS"""
+ temple: """TEMPLE GEIST"""
+ training: """CLEARMAN'S TRAINING"""
+ eternal_rest: """ETERNAL REST CHAMBER"""
+ forbidden_crypt: """FORBIDDEN CRYPT"""
+
+ blacksmith_inside: "A YOUNG GNOME MATERIALIZES, ASKING,\n""WOULD YOU BE WANTING MY SERVICES(Y/N)?"""
+ inn_inside: "AN EERIE SILENCE PERVADES THE DESERTED\nINN. SUDDENLY, A GHOSTLY APPARITION\nAPPEARS, ASKING, ""SIGN IN (Y/N)?"""
+ market_inside: "A FAINT OUTLINE OF A MAN APPEARS,\nSAYING, ""NEED SOME FEED (Y/N)?"""
+ tavern_inside: "STEP UP TO THE BAR (Y/N)?'"
+ temple_inside: "BRIGHT LIGHTS SWIRL THROUGHOUT THE ROOM.A HORRIFYING VOICE SHRIEKS,\n""NEED HELP (Y/N)?"""
+ training_inside: "SEVERAL EMPTY SUITS OF ARMOR APPROACH\nASKING, ""NEED TRAINING (Y/N)?"""
+
+ stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
+ passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+
+ telgoran1: "AN ELF DRESSED IN ROBES APPROACHES...\n\n"
+ telgoran2: """FRIENDS, I AM TELGORAN. THIS SCROLL YOU\nHAVE BROUGHT ME WILL BE VERY HELPFUL',0Dh,'(+2500 EXP) HERE'S 1500 GOLD FOR YOUR\nSERVICES. I'LL TELL YOU A SECRET, IF\nTREASURE IS WHAT YOU WANT..."""
+ telgoran3: """THE BROTHERS YOU MUST FIND...',0Dh,'PORTSMITH AND ALGARY ARE COMBINED."""
+ telgoran4: """YOU'RE NOT THE COURIERS!"""
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 5564f3e224f..33b95c7f800 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -64,7 +64,9 @@ enum Resistance {
};
enum CharFlags0 {
- CHARFLAG0_COURIER = 4,
+ CHARFLAG0_1 = 1,
+ CHARFLAG0_COURIER1 = 2,
+ CHARFLAG0_COURIER2 = 4,
CHARFLAG0_ZOM_CLUE = 8,
CHARFLAG0_ZAM_CLUE = 0x10
};
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 4ba61fe48b5..ec13b282d18 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -150,6 +150,16 @@ void Events::clearViews() {
_views.clear();
}
+void Events::addAction(KeybindingAction action) {
+ Common::Event e;
+ e.type = Common::EVENT_CUSTOM_BACKEND_ACTION_START;
+ e.customType = action;
+ g_system->getEventManager()->pushEvent(e);
+
+ e.type = Common::EVENT_CUSTOM_BACKEND_ACTION_END;
+ g_system->getEventManager()->pushEvent(e);
+}
+
/*------------------------------------------------------------------------*/
Bounds::Bounds(Common::Rect &innerBounds) :
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 9c8490a323c..c4d25455609 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -315,6 +315,8 @@ public:
focusedView()->drawElements();
}
+ void addAction(KeybindingAction action);
+
void draw() override {}
bool tick() override {
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index 92265f9f85c..4eb1a3b4fe1 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -59,13 +59,13 @@ void Map01::special01() {
bool hasCourier = false;
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
- hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER) != 0;
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER2) != 0;
}
if (hasCourier) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._flags[0] |= CHARFLAG0_COURIER | CHARFLAG0_ZAM_CLUE;
+ c._flags[0] |= CHARFLAG0_COURIER2 | CHARFLAG0_ZAM_CLUE;
}
line2 = STRING["maps.map01.zam2"];
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 4289e98aa3f..638ef0041b4 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -65,13 +65,13 @@ void Map02::special01() {
bool hasCourier = false;
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
- hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER) != 0;
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER2) != 0;
}
if (hasCourier) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._flags[0] |= CHARFLAG0_COURIER | CHARFLAG0_ZOM_CLUE;
+ c._flags[0] |= CHARFLAG0_COURIER2 | CHARFLAG0_ZOM_CLUE;
}
line2 = STRING["maps.map02.zom2"];
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 5b05cd489b7..be1a71b4a1b 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -29,9 +29,12 @@ namespace MM {
namespace MM1 {
namespace Maps {
+static const byte MONSTER_ID1[8] = { 5, 10, 12, 2, 11, 16, 6, 12 };
+static const byte MONSTER_ID2[8] = { 2, 7, 7, 7, 5, 4, 3, 8 };
+
void Map03::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 29; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
@@ -44,14 +47,183 @@ void Map03::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map03::special00() {
+ inn();
+}
+
+void Map03::special01() {
+ bool hasCourier = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER2) != 0;
+ }
+
+ bool hasScroll = false;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ for (uint j = 0; j < c._equipped.size() && !hasScroll; ++j) {
+ if (c._equipped[i]._id == 231) {
+ hasScroll = true;
+ c._gold += 1500;
+ break;
+ }
+ }
+ }
+
+ if (hasCourier && hasScroll) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ c._exp += 2500;
+
+ for (uint j = 0; j < c._equipped.size(); ++j) {
+ if (c._equipped[j]._id == 231) {
+ c._equipped.removeAt(j);
+ break;
+ }
+ }
+ }
+
+ InfoMessage info1(
+ 0, 0, STRING["maps.map03.telgoran1"],
+ 0, 1, STRING["maps.map03.zam2"],
+ [](const Common::KeyState &) {
+ InfoMessage info2(
+ 0, 0, STRING["maps.map03.telgoran1"],
+ 0, 1, STRING["maps.map03.zam3"],
+ [](const Common::KeyState &) {
+ g_events->close();
+ }
+ );
+
+ info2._largeMessage = true;
+ g_events->send(info2);
+ }
+ );
+ info1._largeMessage = true;
+ g_events->send(info1);
+
+ } else {
+ send(InfoMessage(
+ 0, 0, STRING["maps.map03.telgoran1"],
+ 0, 1, STRING["maps.map03.zam4"]
+ ));
+ }
+}
+
+void Map03::special02() {
+ blacksmith();
+}
+
+void Map03::special03() {
+ market();
+}
+
+void Map03::special04() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map01.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(9, 11);
+ g_maps->changeMap(0x112, 2);
+ }
+ ));
+}
+
+void Map03::special05() {
+ tavern();
+}
+
+void Map03::special06() {
+ temple();
+}
+
+void Map03::special07() {
+ trainer();
+}
+
+void Map03::special08() {
+ g_globals->_treasure[1] = 9;
+ g_globals->_treasure[4] = 200;
+ g_globals->_treasure[7] = 200;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map03::special09() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map01.stairs"],
+ []() {
+ g_maps->_mapPos = Common::Point(14, 0);
+ g_maps->changeMap(5, 1);
+ }
+ ));
+}
+
+void Map03::special10() {
+ showSign(STRING["maps.map03.market"]);
+}
+
+void Map03::special11() {
+ showSign(STRING["maps.map03.blacksmith"]);
+}
+
+void Map03::special12() {
+ showSign(STRING["maps.map03.inn"]);
+}
+
+void Map03::special13() {
+ _data[0x1d] = 80;
+ _data[0x2e] = 3;
+ _data[0x2f] = 3;
+}
+
+void Map03::special14() {
+ _data[0x1d] = 150;
+ _data[0x2e] = 2;
+ _data[0x2f] = 2;
+}
+
+void Map03::special15() {
+ assert(g_maps->_mapPos.x < 8);
+ g_maps->clearSpecial();
+ int monsterCount = (g_maps->_mapPos.x < 3) ? 1 :
+ getRandomNumber(8);
+
+ Game::Encounter &enc = g_globals->_encounters;
+ enc._levelIndex = 80;
+ enc._flag = true;
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(MONSTER_ID1[i], MONSTER_ID2[i]);
+
+ enc.execute();
+}
+
+void Map03::special18() {
+ showSign(STRING["maps.map03.temple"]);
+}
+
+void Map03::special20() {
+ showSign(STRING["maps.map03.tavern"]);
+}
+
+void Map03::special21() {
+ showSign(STRING["maps.map03.training"]);
+}
+
+void Map03::special27() {
+ showSign(STRING["maps.map03.forbidden_crypt"]);
+}
+
+void Map03::special28() {
+ showSign(STRING["maps.map03.eternal_rest"]);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map03.h b/engines/mm/mm1/maps/map03.h
index 642035e2873..ce83e458729 100644
--- a/engines/mm/mm1/maps/map03.h
+++ b/engines/mm/mm1/maps/map03.h
@@ -32,9 +32,57 @@ class Map03 : public MapTown {
typedef void (Map03:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special18();
+ void special20();
+ void special21();
+ void special27();
+ void special28();
- const SpecialFn SPECIAL_FN[1] = {
- &Map03::special00
+ const SpecialFn SPECIAL_FN[29] = {
+ &Map03::special00,
+ &Map03::special01,
+ &Map03::special02,
+ &Map03::special03,
+ &Map03::special04,
+ &Map03::special05,
+ &Map03::special06,
+ &Map03::special07,
+ &Map03::special08,
+ &Map03::special09,
+ &Map03::special10,
+ &Map03::special11,
+ &Map03::special12,
+ &Map03::special13,
+ &Map03::special14,
+ &Map03::special15,
+ &Map03::special15,
+ &Map03::special15,
+ &Map03::special18,
+ &Map03::special15,
+ &Map03::special20,
+ &Map03::special21,
+ &Map03::special15,
+ &Map03::special15,
+ &Map03::special15,
+ &Map03::special15,
+ &Map03::special15,
+ &Map03::special27,
+ &Map03::special28
};
public:
Map03() : MapTown(3, "dusk", 0x802) {}
Commit: b2eff4bf23321409a5daa620762686371ba4d6cb
https://github.com/scummvm/scummvm/commit/b2eff4bf23321409a5daa620762686371ba4d6cb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: In progress map 4, custom view for guards arresting
Changed paths:
A engines/mm/mm1/views/maps/arrested.cpp
A engines/mm/mm1/views/maps/arrested.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map04.h
engines/mm/mm1/maps/map_town.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c287cf56ce7..9b319f95656 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -814,8 +814,9 @@ monster_spells:
10: "IS AFFECTED"
maps:
+ sign: "A SIGN ABOVE THE DOOR READS:\n"
+
map00:
- sign: "A SIGN ABOVE THE DOOR READS: "
blacksmith: """B AND B BLACKSMITHING"""
inn: """THE INN OF SORPIGAL"""
jail: "JAIL. KEEP OUT!"
@@ -839,7 +840,6 @@ maps:
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
map01:
- sign: "A SIGN ABOVE THE DOOR READS:\n"
blacksmith: """B. SMITH',27h,'S WORKSHOP"""
inn: """INN OF PORTSMITH"""
market: """MAID MARION'S MARKET"""
@@ -864,7 +864,6 @@ maps:
zam3: "YOU'RE NOT THE COURIERS!"""
map02:
- sign: "A SIGN ABOVE THE DOOR READS:\n"
blacksmith: """SWAMPSIDE SUPPLIES"""
inn: """THE INN OF ALGARY"""
market: """ARCON'S SLOP"""
@@ -892,7 +891,6 @@ maps:
zom3: "YOU'RE NOT THE COURIERS!"""
map03:
- sign: "A SIGN ABOVE THE DOOR READS:\n"
blacksmith: """MYSTICAL METAL WORKS"""
inn: """THE INN OF DUSK"""
market: """FEWLERD'S FEED"""
@@ -916,3 +914,28 @@ maps:
telgoran2: """FRIENDS, I AM TELGORAN. THIS SCROLL YOU\nHAVE BROUGHT ME WILL BE VERY HELPFUL',0Dh,'(+2500 EXP) HERE'S 1500 GOLD FOR YOUR\nSERVICES. I'LL TELL YOU A SECRET, IF\nTREASURE IS WHAT YOU WANT..."""
telgoran3: """THE BROTHERS YOU MUST FIND...',0Dh,'PORTSMITH AND ALGARY ARE COMBINED."""
telgoran4: """YOU'RE NOT THE COURIERS!"""
+
+ map04:
+ blacksmith: """CURRENT TRENDS IRONWORKS"""
+ inn: """THE INN OF ERLIQUIN"""
+ market: """FOUR STAR FOODS"""
+ tavern: """TAVERN OF TALL TALES"""
+ temple: """TEMPLE GAUCHE"""
+ training: """SUPERIOR TRAINING"""
+
+ blacksmith_inside: "A BOISTROUS HALF-ORC PROCLAIMS,\n""WE CARRY THE VERY LATEST,\nBROWSE (Y/N)?"""
+ inn_inside: "ADJUSTING HIS SPECTACLES, AN ELDERLY\nGNOME EYES THE PARTY AND ASKS,\n""SIGNING IN (Y/N)?"""
+ market_inside: "THE CHEF SAYS,""I ONLY SERVE THE BEST!\nHUNGRY (Y/N)?"""
+ tavern_inside: "STEP UP TO THE BAR (Y/N)?"
+ training_inside: "THREE HUGE ARMOR CLAD KNIGHTS BARK IN\nUNISON, ""WANT A GOOD WORKOUT (Y/N)?"""
+ temple_inside: "SEVERAL FAT CLERICS WELCOME YOU.\nNEED HELP (Y/N)?"
+
+ agar1: "THE WIZARD AGAR SPEAKS:\n\n"
+ agar2: """YOU HAVE DONE WELL TO BRING ME THIS\nSCROLL. (+1000 EXP) NOW TAKE IT TO MY\nPROTEGE TELGORAN IN DUSK."""
+ agar3: """I HAVE NO BUSINESS WITH YOU. BEGONE!"""
+ guards: "TOWN GUARDS: YOU'RE UNDER ARREST!\n\nA)ATTACK B)BRIBE C)RUN D)SURRENDER"
+ passage_outside: "PASSAGE OUTSIDE, EXIT (Y/N)?"
+ poof: "POOF!"
+ sentence: "HIGH COURT SENTENCE: YEARS= "
+ stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
+ treasure: "TOWN TREASURE, STEAL (Y/N)?"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 33b95c7f800..c9ebd7c5eb9 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -64,9 +64,9 @@ enum Resistance {
};
enum CharFlags0 {
- CHARFLAG0_1 = 1,
- CHARFLAG0_COURIER1 = 2,
- CHARFLAG0_COURIER2 = 4,
+ CHARFLAG0_COURIER1 = 1,
+ CHARFLAG0_COURIER2 = 2,
+ CHARFLAG0_COURIER3 = 4,
CHARFLAG0_ZOM_CLUE = 8,
CHARFLAG0_ZAM_CLUE = 0x10
};
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index c483691f02c..3e1cf18582f 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -80,7 +80,7 @@ void Map00::special01() {
}
send(InfoMessage(
- 2, 0, STRING["maps.map00.sign"],
+ 2, 0, STRING["maps.sign"],
x, 1, line2
));
}
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index 4eb1a3b4fe1..f5045920df6 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -59,13 +59,13 @@ void Map01::special01() {
bool hasCourier = false;
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
- hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER2) != 0;
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER3) != 0;
}
if (hasCourier) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._flags[0] |= CHARFLAG0_COURIER2 | CHARFLAG0_ZAM_CLUE;
+ c._flags[0] |= CHARFLAG0_COURIER3 | CHARFLAG0_ZAM_CLUE;
}
line2 = STRING["maps.map01.zam2"];
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 638ef0041b4..f45b2787293 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -65,13 +65,13 @@ void Map02::special01() {
bool hasCourier = false;
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
- hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER2) != 0;
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER3) != 0;
}
if (hasCourier) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._flags[0] |= CHARFLAG0_COURIER2 | CHARFLAG0_ZOM_CLUE;
+ c._flags[0] |= CHARFLAG0_COURIER3 | CHARFLAG0_ZOM_CLUE;
}
line2 = STRING["maps.map02.zom2"];
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index be1a71b4a1b..acee48bf98b 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -60,7 +60,7 @@ void Map03::special00() {
void Map03::special01() {
bool hasCourier = false;
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
- hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER2) != 0;
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER3) != 0;
}
bool hasScroll = false;
@@ -91,11 +91,11 @@ void Map03::special01() {
InfoMessage info1(
0, 0, STRING["maps.map03.telgoran1"],
- 0, 1, STRING["maps.map03.zam2"],
+ 0, 1, STRING["maps.map03.telgoran2"],
[](const Common::KeyState &) {
InfoMessage info2(
0, 0, STRING["maps.map03.telgoran1"],
- 0, 1, STRING["maps.map03.zam3"],
+ 0, 1, STRING["maps.map03.telgoran3"],
[](const Common::KeyState &) {
g_events->close();
}
@@ -111,7 +111,7 @@ void Map03::special01() {
} else {
send(InfoMessage(
0, 0, STRING["maps.map03.telgoran1"],
- 0, 1, STRING["maps.map03.zam4"]
+ 0, 1, STRING["maps.map03.telgoran4"]
));
}
}
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 3c1700ec6db..5c077c9f4df 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -31,11 +31,11 @@ namespace Maps {
void Map04::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 22; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[73 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +44,126 @@ void Map04::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ // Stealable treasure
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map04.treasure"],
+ []() {
+ g_maps->clearSpecial();
+ if ((*g_maps->_currentMap)[MAP04_TREASURE_STOLEN] < 255)
+ (*g_maps->_currentMap)[MAP04_TREASURE_STOLEN]++;
+ g_globals->_treasure[5] = 88;
+ g_globals->_treasure[6] = 2;
+ g_globals->_treasure[7] = 10;
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ ));
}
void Map04::special00() {
+ inn();
+}
+
+void Map04::special01() {
+ bool hasCourier = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
+ hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER1) != 0;
+ }
+
+ bool hasScroll = false;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ for (uint j = 0; j < c._equipped.size() && !hasScroll; ++j) {
+ if (c._equipped[i]._id == 231) {
+ hasScroll = true;
+ c._gold += 1500;
+ break;
+ }
+ }
+ }
+
+ if (hasCourier && hasScroll) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ c._exp += 1000;
+ c._flags[0] &= (c._flags[0] & CHARFLAG0_COURIER1) | CHARFLAG0_COURIER2;
+ }
+
+ send(InfoMessage(
+ 0, 0, STRING["maps.map04.agar1"],
+ 0, 1, STRING["maps.map04.agar2"],
+ [](const Common::KeyState &) {
+ }
+ ));
+ } else {
+ send(InfoMessage(
+ 0, 0, STRING["maps.map03.telgoran1"],
+ 0, 1, STRING["maps.map03.agar3"]
+ ));
+ }
+}
+
+void Map04::special02() {
+ blacksmith();
+}
+
+void Map04::special03() {
+ market();
+}
+
+void Map04::special04() {
+ if (_data[MAP04_TREASURE_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map04.passage_outside"],
+ []() {
+ g_maps->_mapPos.x = 13;
+ g_maps->_mapPos.y = 1;
+ g_maps->changeMap(0xa00, 2);
+ }
+ ));
+ } else {
+ // Sucks to be you
+ g_events->addView("Arrested");
+ }
+}
+
+void Map04::special05() {
+}
+
+void Map04::special06() {
+}
+
+void Map04::special07() {
+}
+
+void Map04::special08() {
+}
+
+void Map04::special09() {
+}
+
+void Map04::special10() {
+}
+
+void Map04::special11() {
+}
+
+void Map04::special12() {
+}
+
+void Map04::special13() {
+}
+
+void Map04::special18() {
+}
+
+void Map04::special20() {
+}
+
+void Map04::special21() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map04.h b/engines/mm/mm1/maps/map04.h
index 0454c4f65ad..4a15b7b90d6 100644
--- a/engines/mm/mm1/maps/map04.h
+++ b/engines/mm/mm1/maps/map04.h
@@ -28,13 +28,53 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define MAP04_TREASURE_OVERRIDE 169
+#define MAP04_TREASURE_STOLEN 971
+
class Map04 : public MapTown {
typedef void (Map04:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special18();
+ void special20();
+ void special21();
- const SpecialFn SPECIAL_FN[1] = {
- &Map04::special00
+ const SpecialFn SPECIAL_FN[22] = {
+ &Map04::special00,
+ &Map04::special01,
+ &Map04::special02,
+ &Map04::special03,
+ &Map04::special04,
+ &Map04::special05,
+ &Map04::special06,
+ &Map04::special07,
+ &Map04::special08,
+ &Map04::special09,
+ &Map04::special10,
+ &Map04::special11,
+ &Map04::special12,
+ &Map04::special13,
+ &Map04::special13,
+ &Map04::special13,
+ &Map04::special13,
+ &Map04::special13,
+ &Map04::special18,
+ &Map04::special13,
+ &Map04::special20,
+ &Map04::special21
};
public:
Map04() : MapTown(4, "erliquin", 0x0B1A) {}
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
index ceddb102930..4226b9bd574 100644
--- a/engines/mm/mm1/maps/map_town.cpp
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -92,7 +92,7 @@ void MapTown::trainer() {
void MapTown::showSign(const Common::String &msg) {
Sound::sound(SOUND_2);
send(InfoMessage(
- 2, 1, STRING[Common::String::format("maps.map%.2u.sign", _mapIndex)],
+ 2, 1, STRING["maps.sign"],
6, 2, msg
));
}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 2d7360bbf8a..800143d2ea5 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -43,6 +43,7 @@
#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
+#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/views/spells/detect_magic.h"
@@ -79,6 +80,7 @@ private:
Views::Locations::Temple _temple;
Views::Locations::Training _training;
+ Views::Maps::Arrested _arrested;
Views::Maps::Resistances _resistances;
Views::Spells::CastSpell _castSpell;
diff --git a/engines/mm/mm1/views/maps/arrested.cpp b/engines/mm/mm1/views/maps/arrested.cpp
new file mode 100644
index 00000000000..9f671d13cd0
--- /dev/null
+++ b/engines/mm/mm1/views/maps/arrested.cpp
@@ -0,0 +1,132 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/arrested.h"
+#include "mm/mm1/maps/map04.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+Arrested::Arrested() : TextView("Arrested") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Arrested::msgFocus(const FocusMessage &msg) {
+ return TextView::msgFocus(msg);
+}
+
+void Arrested::draw() {
+ clearSurface();
+ Sound::sound(SOUND_2);
+
+ writeString(0, 1, STRING["maps.map04.guards"]);
+}
+
+bool Arrested::msgKeypress(const KeypressMessage &msg) {
+ switch (msg.keycode) {
+ case Common::KEYCODE_a:
+ attack();
+ break;
+ case Common::KEYCODE_b:
+ bribe();
+ break;
+ case Common::KEYCODE_c:
+ run();
+ break;
+ case Common::KEYCODE_d:
+ surrender();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Arrested::attack() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(5);
+ close();
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(6, 10);
+
+ enc._flag = true;
+ enc._levelIndex = 64;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc.execute();
+}
+
+void Arrested::bribe() {
+ if (getRandomNumber(10) == 10) {
+ // Success
+ close();
+ } else {
+ // 8 year sentence for attempted bribery
+ surrender(8);
+ }
+}
+
+void Arrested::run() {
+ g_globals->_currCharacter = &g_globals->_party[
+ getRandomNumber(g_globals->_party.size()) - 1
+ ];
+ g_globals->_currCharacter->_condition = ERADICATED;
+
+ // Pick random run destination. This seems incredibly dangerous,
+ // since couldn't it end up with the party in a wall?
+ g_maps->_mapPos.x = getRandomNumber(15);
+ g_maps->_mapPos.y = getRandomNumber(15);
+
+ clearSurface();
+ writeString(0, 1, STRING["maps.map04.poof"]);
+ delaySeconds(2);
+}
+
+void Arrested::surrender(int numYears) {
+ // Characters are aged by their prision sentence, and their gold halved
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ if ((int)c._age._base + numYears < 256)
+ c._age._base += numYears;
+ c._gold /= 2;
+ }
+
+ // Display sentence
+ clearSurface();
+ Sound::sound(SOUND_2);
+ writeString(0, 1, STRING["maps.map04.sentence"]);
+ writeNumber('0' + numYears);
+
+ (*g_maps->_currentMap)[MAP04_TREASURE_STOLEN] = 0;
+ delaySeconds(3);
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/arrested.h b/engines/mm/mm1/views/maps/arrested.h
new file mode 100644
index 00000000000..cfb89d418f7
--- /dev/null
+++ b/engines/mm/mm1/views/maps/arrested.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_ARRESTED_H
+#define MM1_VIEWS_MAPS_ARRESTED_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Arrested : public TextView {
+private:
+ void attack();
+ void bribe();
+ void run();
+ void surrender(int numYears = 2);
+
+public:
+ Arrested();
+ virtual ~Arrested() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 94360e3cc90..308fb9f9d02 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -50,6 +50,7 @@ MODULE_OBJS := \
mm1/views/locations/tavern.o \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
+ mm1/views/maps/arrested.o \
mm1/views/maps/resistances.o \
mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
Commit: 5ac771142ca7480fc0ccb1367261bf5ac931cb07
https://github.com/scummvm/scummvm/commit/5ac771142ca7480fc0ccb1367261bf5ac931cb07
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:19+01:00
Commit Message:
MM: MM1: Remainder of map 4 implemented
Changed paths:
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map04.h
engines/mm/mm1/maps/map_town.cpp
engines/mm/mm1/maps/map_town.h
engines/mm/mm1/views/maps/arrested.cpp
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 3e1cf18582f..a4b3e04df7a 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -113,7 +113,7 @@ void Map00::special06() {
}
void Map00::special07() {
- trainer();
+ training();
}
void Map00::special08() {
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index f5045920df6..c386754f3b9 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -105,7 +105,7 @@ void Map01::special06() {
}
void Map01::special07() {
- trainer();
+ training();
}
void Map01::special08() {
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index f45b2787293..08482f05dd9 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -112,7 +112,7 @@ void Map02::special06() {
}
void Map02::special07() {
- trainer();
+ training();
}
void Map02::special08() {
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index acee48bf98b..96c72ac5125 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -144,7 +144,7 @@ void Map03::special06() {
}
void Map03::special07() {
- trainer();
+ training();
}
void Map03::special08() {
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 5c077c9f4df..f8c1335440c 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -114,7 +114,7 @@ void Map04::special03() {
}
void Map04::special04() {
- if (_data[MAP04_TREASURE_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
+ if (_data[MAP04_PASSAGE_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
Sound::sound(SOUND_2);
send(InfoMessage(
STRING["maps.map04.passage_outside"],
@@ -131,39 +131,78 @@ void Map04::special04() {
}
void Map04::special05() {
+ tavern();
}
void Map04::special06() {
+ temple();
}
void Map04::special07() {
+ training();
}
void Map04::special08() {
+ // Pick random run destination. This seems incredibly dangerous,
+ // since couldn't it end up with the party in a wall?
+ g_maps->_mapPos.x = getRandomNumber(15);
+ g_maps->_mapPos.y = getRandomNumber(15);
+
+ send(InfoMessage(0, 1, STRING["maps.map04.poof"]));
}
void Map04::special09() {
+ if (_data[MAP04_STAIRS_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
+ if (_data[MAP04_STAIRS_OVERRIDE] < 255)
+ _data[MAP04_STAIRS_OVERRIDE]++;
+
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map04.stairs"],
+ []() {
+ g_maps->_mapPos.x = 0;
+ g_maps->_mapPos.y = 7;
+ g_maps->changeMap(0x202, 2);
+ }
+ ));
+ } else {
+ // Sucks to be you
+ g_events->addView("Arrested");
+ }
}
void Map04::special10() {
+ showSign(STRING["maps.map04.market"]);
}
void Map04::special11() {
+ showSign(STRING["maps.map04.blacksmith"]);
}
void Map04::special12() {
+ showSign(STRING["maps.map04.inn"]);
}
void Map04::special13() {
+ if (_data[MAP04_TREASURE_STOLEN]) {
+ g_maps->clearSpecial();
+ g_events->addView("Arrested");
+ } else {
+ // TODO: Sends key 160 to game_keypress, which doesn't seem to handle it
+ //g_events->addAction();
+ }
}
void Map04::special18() {
+ showSign(STRING["maps.map04.temple"]);
}
void Map04::special20() {
+ showSign(STRING["maps.map04.tavern"]);
}
void Map04::special21() {
+ showSign(STRING["maps.map04.training"]);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map04.h b/engines/mm/mm1/maps/map04.h
index 4a15b7b90d6..b52627f238a 100644
--- a/engines/mm/mm1/maps/map04.h
+++ b/engines/mm/mm1/maps/map04.h
@@ -28,7 +28,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define MAP04_TREASURE_OVERRIDE 169
+#define MAP04_PASSAGE_OVERRIDE 169
+#define MAP04_STAIRS_OVERRIDE 196
#define MAP04_TREASURE_STOLEN 971
class Map04 : public MapTown {
@@ -42,7 +43,6 @@ private:
void special05();
void special06();
void special07();
- void special08();
void special09();
void special10();
void special11();
@@ -83,6 +83,8 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ void special08();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
index 4226b9bd574..ed474acf147 100644
--- a/engines/mm/mm1/maps/map_town.cpp
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -79,7 +79,7 @@ void MapTown::temple() {
));
}
-void MapTown::trainer() {
+void MapTown::training() {
Sound::sound(SOUND_2);
send(InfoMessage(
STRING[Common::String::format("maps.map%.2u.training_inside", _mapIndex)],
diff --git a/engines/mm/mm1/maps/map_town.h b/engines/mm/mm1/maps/map_town.h
index ff4889cb40e..0f456f2a85a 100644
--- a/engines/mm/mm1/maps/map_town.h
+++ b/engines/mm/mm1/maps/map_town.h
@@ -58,7 +58,7 @@ protected:
/**
* Handles visiting trainer
*/
- void trainer();
+ void training();
/**
* Show a sign message
diff --git a/engines/mm/mm1/views/maps/arrested.cpp b/engines/mm/mm1/views/maps/arrested.cpp
index 9f671d13cd0..3844e9ee4d1 100644
--- a/engines/mm/mm1/views/maps/arrested.cpp
+++ b/engines/mm/mm1/views/maps/arrested.cpp
@@ -91,19 +91,13 @@ void Arrested::bribe() {
}
void Arrested::run() {
+ close();
g_globals->_currCharacter = &g_globals->_party[
getRandomNumber(g_globals->_party.size()) - 1
];
g_globals->_currCharacter->_condition = ERADICATED;
- // Pick random run destination. This seems incredibly dangerous,
- // since couldn't it end up with the party in a wall?
- g_maps->_mapPos.x = getRandomNumber(15);
- g_maps->_mapPos.y = getRandomNumber(15);
-
- clearSurface();
- writeString(0, 1, STRING["maps.map04.poof"]);
- delaySeconds(2);
+ static_cast<MM1::Maps::Map04 *>(g_maps->_currentMap)->special08();
}
void Arrested::surrender(int numYears) {
Commit: 70ad0e7ae0a2b75cded034a50afff047e0ff43e6
https://github.com/scummvm/scummvm/commit/70ad0e7ae0a2b75cded034a50afff047e0ff43e6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: Most of map 5 implemented
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map05.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9b319f95656..926f64e94eb 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -939,3 +939,12 @@ maps:
sentence: "HIGH COURT SENTENCE: YEARS= "
stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
treasure: "TOWN TREASURE, STEAL (Y/N)?"
+
+ map05:
+ arena: """THE ARENA"""
+ arena_inside: "AROUND THE ROOM THERE ARE SEVERAL\nBALCONIES FILLED WITH CHEERING PEASANTS\nA MAN ASKS ""WILL YOU PARTICIPATE (Y/N)?"""
+ portal: "A SHIMMERING BLUE AND WHITE PORTAL\nAPPEARS! ENTER (Y/N)?"
+ stairs: "STAIRS GOING UP! TAKE THEM (Y/N)?"
+ message1:"SCRAWLED ON THE WALL, A MESSAGE READS:\n"
+ message2: "THE JAIL ABOVE HAS MANY CELLS."
+ message3: "DON'T TURN AROUND!"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index a795ac4fb84..6b5a2d74112 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -29,7 +29,7 @@
namespace MM {
namespace MM1 {
-#define TREASURE_COUNT 8
+#define TREASURE_COUNT 9
enum EnablementBit {
KNIGHT_BIT = 0x20, PALADIN_BIT = 0x10, ARCHER_BIT = 8,
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index d08830fedaa..7e817eda874 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -324,19 +324,19 @@ void Combat::proc1() {
_val6 = MAX(_val6, _val7);
if (_val7 & 1)
- g_globals->_treasure[7] += getRandomNumber(6);
+ g_globals->_treasure[8] += getRandomNumber(6);
if (_val7 & 6) {
if (!(_val7 & 2)) {
- WRITE_LE_UINT16(&g_globals->_treasure[5],
- READ_LE_UINT16(&g_globals->_treasure[5]) +
+ WRITE_LE_UINT16(&g_globals->_treasure[6],
+ READ_LE_UINT16(&g_globals->_treasure[6]) +
getRandomNumber(10));
} else if (!(_val7 & 4)) {
- WRITE_LE_UINT16(&g_globals->_treasure[5],
- READ_LE_UINT16(&g_globals->_treasure[5]) +
+ WRITE_LE_UINT16(&g_globals->_treasure[6],
+ READ_LE_UINT16(&g_globals->_treasure[6]) +
getRandomNumber(100));
} else {
- g_globals->_treasure[6] += getRandomNumber(4);
+ g_globals->_treasure[7] += getRandomNumber(4);
}
}
}
@@ -351,22 +351,22 @@ void Combat::selectTreasure() {
#undef SHIFT_BIT
auto &treasure = g_globals->_treasure;
- treasure[0] = 0;
+ treasure[1] = 0;
if (_treasureFlags[4]) {
- treasure[1] = 10;
+ treasure[2] = 10;
} else if (_treasureFlags[3]) {
- treasure[1] = 5 + getRandomNumber(4);
+ treasure[2] = 5 + getRandomNumber(4);
} else if (_treasureFlags[2]) {
- treasure[1] = 4 + getRandomNumber(4);
+ treasure[2] = 4 + getRandomNumber(4);
} else if (_treasureFlags[1]) {
- treasure[1] = 3 + getRandomNumber(4);
- } else if (_treasureFlags[0] || treasure[7]) {
- treasure[1] = 1 + getRandomNumber(4);
- } else if (treasure[6]) {
- treasure[1] = getRandomNumber(4) - 1;
+ treasure[2] = 3 + getRandomNumber(4);
+ } else if (_treasureFlags[0] || treasure[8]) {
+ treasure[2] = 1 + getRandomNumber(4);
+ } else if (treasure[7]) {
+ treasure[2] = getRandomNumber(4) - 1;
} else {
- treasure[1] = getRandomNumber(2) - 1;
+ treasure[2] = getRandomNumber(2) - 1;
}
}
@@ -388,12 +388,12 @@ void Combat::selectTreasure2(int count) {
_val1 += getRandomNumber(_allowFight) - 1;
auto &treasure = g_globals->_treasure;
- if (!treasure[2])
- treasure[2] = _val1;
- else if (!treasure[3])
+ if (!treasure[3])
treasure[3] = _val1;
else if (!treasure[4])
treasure[4] = _val1;
+ else if (!treasure[5])
+ treasure[5] = _val1;
}
void Combat::nextRound() {
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 96c72ac5125..b0cf630fdb5 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -148,9 +148,9 @@ void Map03::special07() {
}
void Map03::special08() {
- g_globals->_treasure[1] = 9;
- g_globals->_treasure[4] = 200;
- g_globals->_treasure[7] = 200;
+ g_globals->_treasure[2] = 9;
+ g_globals->_treasure[5] = 200;
+ g_globals->_treasure[8] = 200;
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index f8c1335440c..2acf595de9c 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -53,9 +53,9 @@ void Map04::special() {
g_maps->clearSpecial();
if ((*g_maps->_currentMap)[MAP04_TREASURE_STOLEN] < 255)
(*g_maps->_currentMap)[MAP04_TREASURE_STOLEN]++;
- g_globals->_treasure[5] = 88;
- g_globals->_treasure[6] = 2;
- g_globals->_treasure[7] = 10;
+ g_globals->_treasure[6] = 88;
+ g_globals->_treasure[7] = 2;
+ g_globals->_treasure[8] = 10;
g_events->addAction(KEYBIND_SEARCH);
}
));
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 5e47d60f36c..9ba482b5771 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define MONSTER_ID 169
+
void Map05::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 21; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[72 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,140 @@ void Map05::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map05::special00() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map05.stairs"],
+ []() {
+ g_maps->changeMap(0x604, 1);
+ }
+ ));
+}
+
+void Map05::special01() {
+ encounter(1);
+}
+
+void Map05::special02() {
+ encounter(9);
+}
+
+void Map05::special03() {
+ encounter(14);
+}
+
+void Map05::special04() {
+ encounter(20);
+}
+
+void Map05::special05() {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+
+ enc.clearMonsters();
+ for (int i = 0; i < 10; ++i)
+ enc.addMonster(14, 1);
+
+ enc._levelIndex = 80;
+ enc._flag = true;
+ enc.execute();
+}
+
+void Map05::special06() {
+ // TODO: special
+}
+
+void Map05::special07() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map05.portal"],
+ []() {
+ g_maps->_mapPos.x = 8;
+ g_maps->_mapPos.y = 8;
+ g_maps->changeMap(1, 1);
+ }
+ ));
+}
+
+void Map05::special08() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 2, 1, STRING["maps.sign"],
+ 10, 2, STRING["maps.map05.arena"]
+ ));
+}
+
+void Map05::special09() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 0, 1, STRING["maps.map05.arena_inside"],
+ [](const Common::KeyState &keyState) {
+ if (keyState.keycode == Common::KEYCODE_y) {
+ (*g_maps->_currentMap)[MAP_47] = 2;
+ (*g_maps->_currentMap)[MAP_33] = 6;
+ (*g_maps->_currentMap)[MAP_MAX_MONSTERS] = 15;
+ g_globals->_encounters._encounterType = Game::FORCE_SURPRISED;
+ g_globals->_encounters.execute();
+
+ } else if (keyState.keycode == Common::KEYCODE_n) {
+ (*g_maps->_currentMap)[MAP_47] = 1;
+ (*g_maps->_currentMap)[MAP_33] = 4;
+ (*g_maps->_currentMap)[MAP_MAX_MONSTERS] = 10;
+ Common::fill(&g_globals->_treasure[0], &g_globals->_treasure[TREASURE_COUNT], 0);
+
+// TODO: Space key - is it used in-game?
+// g_events->addAction(32);
+ }
+ }
+ ));
+}
+
+void Map05::special10() {
+ showMessage(STRING["maps.map05.message2"]);
+}
+
+void Map05::special11() {
+ if (g_maps->_forwardMask == DIRMASK_S) {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ } else {
+ showMessage(STRING["maps.map05.message3"]);
+ }
+}
+
+void Map05::special14() {
+ g_maps->clearSpecial();
+ if (getRandomNumber(2) == 2)
+ g_globals->_encounters.execute();
+}
+
+void Map05::encounter(int monsterId) {
+ Game::Encounter &enc = g_globals->_encounters;
+ _data[MONSTER_ID] = monsterId;
+ g_maps->clearSpecial();
+
+ int monsterCount = getRandomNumber(5);
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(monsterId, 1);
+
+ enc._levelIndex = 80;
+ enc._flag = true;
+ enc.execute();
+}
+
+void Map05::showMessage(const Common::String &msg) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 0, 1, STRING["maps.map05.message1"],
+ 0, 2, msg
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map05.h b/engines/mm/mm1/maps/map05.h
index 257d5974091..d8db857a0cb 100644
--- a/engines/mm/mm1/maps/map05.h
+++ b/engines/mm/mm1/maps/map05.h
@@ -32,9 +32,43 @@ class Map05 : public Map {
typedef void (Map05:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special14();
+ void encounter(int monsterId);
+ void showMessage(const Common::String &msg);
- const SpecialFn SPECIAL_FN[1] = {
- &Map05::special00
+ const SpecialFn SPECIAL_FN[21] = {
+ &Map05::special00,
+ &Map05::special01,
+ &Map05::special02,
+ &Map05::special03,
+ &Map05::special04,
+ &Map05::special05,
+ &Map05::special06,
+ &Map05::special07,
+ &Map05::special08,
+ &Map05::special09,
+ &Map05::special10,
+ &Map05::special11,
+ &Map05::special11,
+ &Map05::special11,
+ &Map05::special14,
+ &Map05::special14,
+ &Map05::special14,
+ &Map05::special14,
+ &Map05::special14,
+ &Map05::special14,
+ &Map05::special08
};
public:
Map05() : Map(5, "cave1", 0x0A11) {}
Commit: f793afbff09cc01e01f0caccc27edec2a87f9b35
https://github.com/scummvm/scummvm/commit/f793afbff09cc01e01f0caccc27edec2a87f9b35
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: Remainder of map 5
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map05.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 926f64e94eb..2fad0f2f7f4 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -948,3 +948,8 @@ maps:
message1:"SCRAWLED ON THE WALL, A MESSAGE READS:\n"
message2: "THE JAIL ABOVE HAS MANY CELLS."
message3: "DON'T TURN AROUND!"
+ man1: "AN ELDERLY MAN BEHIND A DESK SPEAKS:\n""I AM IN NEED OF COURIER SERVICE\nARE YOU INTERESTED (Y/N)?"""
+ man2: """I SEE YOU HAVEN'T DELIVERED MY MESSAGE,\nCARE TO TRY AGAIN (Y/N)?"""
+ man3: """GOOD! TAKE THIS SCROLL TO THE\nWIZARD AGAR IN ERLIQUIN AND YOU SHALL\nBE REWARDED."""
+ backpacks_full: "*** BACK PACKS FULL ***"
+
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index d83145199d7..e38c1dd2028 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -104,7 +104,7 @@ void Inventory::remove(Entry *e) {
removeAt(index);
}
-int Inventory::indexOf(Entry *e) {
+int Inventory::indexOf(Entry *e) const {
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
if (e == &_items[i])
return i;
@@ -113,6 +113,15 @@ int Inventory::indexOf(Entry *e) {
return -1;
}
+int Inventory::indexOf(byte itemId) const {
+ for (uint i = 0; i < INVENTORY_COUNT; ++i) {
+ if (_items[i]._id == itemId)
+ return i;
+ }
+
+ return -1;
+}
+
bool Inventory::hasCategory(CategoryFn fn) const {
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
if (fn(_items[i]._id))
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index c9ebd7c5eb9..4192befe01e 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -150,7 +150,12 @@ public:
/**
* Returns the index of a given entry
*/
- int indexOf(Entry *e);
+ int indexOf(Entry *e) const;
+
+ /**
+ * Returns the index of an entry with a given id
+ */
+ int indexOf(byte itemId) const;
/**
* Decreases the charge on a magic item, and removes
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 6b5a2d74112..9795423013e 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -31,6 +31,10 @@ namespace MM1 {
#define TREASURE_COUNT 9
+enum ItemId {
+ SCROLL_ID = 231
+};
+
enum EnablementBit {
KNIGHT_BIT = 0x20, PALADIN_BIT = 0x10, ARCHER_BIT = 8,
CLERIC_BIT = 4, SORCERER_BIT = 2, ROBBER_BIT = 1,
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 2acf595de9c..059546a75e7 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -74,12 +74,10 @@ void Map04::special01() {
bool hasScroll = false;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- for (uint j = 0; j < c._equipped.size() && !hasScroll; ++j) {
- if (c._equipped[i]._id == 231) {
- hasScroll = true;
- c._gold += 1500;
- break;
- }
+ if (c._equipped.indexOf(231) != -1) {
+ hasScroll = true;
+ c._gold += 1500;
+ break;
}
}
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 9ba482b5771..e4be93ba197 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -30,6 +30,8 @@ namespace MM1 {
namespace Maps {
#define MONSTER_ID 169
+#define VAL1 574
+#define VAL2 575
void Map05::special() {
// Scan for special actions on the map cell
@@ -91,7 +93,18 @@ void Map05::special05() {
}
void Map05::special06() {
- // TODO: special
+ if (!hasScroll()) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 0, 1, STRING[!hasFlag() ? "maps.map05.man1" : "maps.map05.man2"],
+ []() {
+ if (addScroll()) {
+ addFlag();
+ g_events->send(InfoMessage(0, 1, STRING["maps.map05.man3"]));
+ }
+ }
+ ));
+ }
}
void Map05::special07() {
@@ -181,6 +194,49 @@ void Map05::showMessage(const Common::String &msg) {
));
}
+bool Map05::hasScroll() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ const Character &c = g_globals->_party[i];
+ if (c._equipped.indexOf(SCROLL_ID) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+bool Map05::addScroll() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!c._backpack.full()) {
+ // Add item
+ c._backpack.add(SCROLL_ID, 0);
+ g_globals->_items.getItem(SCROLL_ID);
+ return true;
+ }
+ }
+
+ Sound::sound(SOUND_2);
+ g_events->send(InfoMessage(8, 2, STRING["maps.map05.backpacks_full"]));
+ return false;
+}
+
+bool Map05::hasFlag() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ const Character &c = g_globals->_party[i];
+ if (c._flags[0] & CHARFLAG0_COURIER1)
+ return true;
+ }
+
+ return false;
+}
+
+void Map05::addFlag() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[0] |= CHARFLAG0_COURIER1;
+ }
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map05.h b/engines/mm/mm1/maps/map05.h
index d8db857a0cb..808a7e15d84 100644
--- a/engines/mm/mm1/maps/map05.h
+++ b/engines/mm/mm1/maps/map05.h
@@ -46,6 +46,10 @@ private:
void special14();
void encounter(int monsterId);
void showMessage(const Common::String &msg);
+ static bool hasScroll();
+ static bool addScroll();
+ static bool hasFlag();
+ static void addFlag();
const SpecialFn SPECIAL_FN[21] = {
&Map05::special00,
Commit: 0424ff5c5798117d598812fbf5d3752210fe0179
https://github.com/scummvm/scummvm/commit/0424ff5c5798117d598812fbf5d3752210fe0179
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: Added map 6
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map06.cpp
engines/mm/mm1/maps/map06.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 2fad0f2f7f4..7048c2ce67b 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -815,6 +815,7 @@ monster_spells:
maps:
sign: "A SIGN ABOVE THE DOOR READS:\n"
+ poof: "POOF!"
map00:
blacksmith: """B AND B BLACKSMITHING"""
@@ -935,7 +936,6 @@ maps:
agar3: """I HAVE NO BUSINESS WITH YOU. BEGONE!"""
guards: "TOWN GUARDS: YOU'RE UNDER ARREST!\n\nA)ATTACK B)BRIBE C)RUN D)SURRENDER"
passage_outside: "PASSAGE OUTSIDE, EXIT (Y/N)?"
- poof: "POOF!"
sentence: "HIGH COURT SENTENCE: YEARS= "
stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
treasure: "TOWN TREASURE, STEAL (Y/N)?"
@@ -953,3 +953,10 @@ maps:
man3: """GOOD! TAKE THIS SCROLL TO THE\nWIZARD AGAR IN ERLIQUIN AND YOU SHALL\nBE REWARDED."""
backpacks_full: "*** BACK PACKS FULL ***"
+ map06:
+ passage_outside: "PASSAGE OUTSIDE, EXIT (Y/N)?"
+ portal: "SHIMMERING BLUE AND WHITE PORTAL,\nENTER (Y/N)?"
+ acid: "SPLASH! A POOL OF ACID!"
+ button: "BUTTON ON THE WALL, PRESS IT (Y/N)?"
+ banner: "A BANNER READS:\nCORRIDOR OF ENDLESS ENCOUNTERS!"
+ wizard: "A CRAZED WIZARD EXCLAIMS,\n""ENCOUNTER THE 13, WIN THE PRIZE!""
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index ec13b282d18..ae1cadbbf10 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -150,6 +150,17 @@ void Events::clearViews() {
_views.clear();
}
+void Events::addKeypress(const Common::KeyCode kc) {
+ Common::Event e;
+ e.type = Common::EVENT_KEYDOWN;
+ e.kbd.keycode = kc;
+ e.kbd.ascii = kc <= 127 ? kc : 0;
+ g_system->getEventManager()->pushEvent(e);
+
+ e.type = Common::EVENT_KEYUP;
+ g_system->getEventManager()->pushEvent(e);
+}
+
void Events::addAction(KeybindingAction action) {
Common::Event e;
e.type = Common::EVENT_CUSTOM_BACKEND_ACTION_START;
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index c4d25455609..cd09a8fcc34 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -315,6 +315,14 @@ public:
focusedView()->drawElements();
}
+ /**
+ * Add a keypress to the event queue
+ */
+ void addKeypress(const Common::KeyCode kc);
+
+ /**
+ * Add a action to the event queue
+ */
void addAction(KeybindingAction action);
void draw() override {}
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 059546a75e7..ad93de343fe 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -146,7 +146,7 @@ void Map04::special08() {
g_maps->_mapPos.x = getRandomNumber(15);
g_maps->_mapPos.y = getRandomNumber(15);
- send(InfoMessage(0, 1, STRING["maps.map04.poof"]));
+ send(InfoMessage(0, 1, STRING["maps.poof"]));
}
void Map04::special09() {
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index e4be93ba197..40eeda36580 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -145,8 +145,8 @@ void Map05::special09() {
(*g_maps->_currentMap)[MAP_MAX_MONSTERS] = 10;
Common::fill(&g_globals->_treasure[0], &g_globals->_treasure[TREASURE_COUNT], 0);
-// TODO: Space key - is it used in-game?
-// g_events->addAction(32);
+ // TODO: Space key - is it used in-game?
+ g_events->addKeypress(Common::KEYCODE_SPACE);
}
}
));
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
index 561cd487170..50c01dc1076 100644
--- a/engines/mm/mm1/maps/map06.cpp
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -29,14 +29,24 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 446
+#define VAL2 447
+#define VAL3 329
+
+static const byte MONSTER_ID1[13] = {
+ 2, 1, 8, 9, 5, 9, 2, 7, 15, 4, 11, 1, 5
+};
+static const byte MONSTER_ID2[13] = {
+ 3, 4, 3, 4, 4, 3, 4, 3, 3, 4, 4, 3, 3
+};
+
void Map06::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 27; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[78 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +54,168 @@ void Map06::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (_data[VAL1]) {
+ _data[VAL2]++;
+
+ Common::Point &pos = g_maps->_mapPos;
+ if (pos.y == 9) {
+ if (pos.x == 13 || pos.x == 14)
+ pos.x++;
+ else
+ pos.y++;
+ } else if (pos.x < 6) {
+ if (pos.y == 0) {
+ if (pos.x == 0)
+ pos.y++;
+ else
+ pos.x--;
+ } else if (pos.y != 10 || pos.x == 3) {
+ pos.y++;
+ } else {
+ pos.x++;
+ }
+ } else if (pos.x == 6) {
+ if (pos.y == 0)
+ pos.x--;
+ else
+ pos.y--;
+ } else {
+ pos.y++;
+ }
+
+ g_events->send("Game", GameMessage("UPDATE"));
+ } else {
+ checkPartyDead();
+ }
}
void Map06::special00() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map06.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(15, 11);
+ g_maps->changeMap(0xa11, 2);
+ }
+ ));
+}
+
+void Map06::special01() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map06.portal"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 0);
+ g_maps->changeMap(0xc01, 1);
+ }
+ ));
+}
+
+void Map06::special02() {
+ if (_data[VAL1]) {
+ slide();
+ } else {
+ checkPartyDead();
+ }
+}
+
+void Map06::special03() {
+ if (_data[VAL1]) {
+ g_maps->_mapPos.y++;
+ slide();
+ } else {
+ checkPartyDead();
+ }
+}
+
+void Map06::special04() {
+ if (_data[VAL2]) {
+ _data[VAL2] = 0;
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map06.acid"]));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._hpBase = MAX((int)c._hpBase - 15, 0);
+ if (!c._hpBase) {
+ if (!(c._condition & BAD_CONDITION))
+ c._condition = UNCONSCIOUS;
+ }
+ }
+ } else {
+ // TODO: Space key - is it used in-game?
+ g_events->addKeypress(Common::KEYCODE_SPACE);
+ }
+}
+
+void Map06::special06() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map06.button"],
+ []() {
+ byte &val1 = (*static_cast<Map06 *>(g_maps->_currentMap))[VAL1];
+ val1 = val1 ? 0 : 1;
+ g_events->addKeypress(Common::KEYCODE_SPACE);
+ }
+ ));
+}
+
+void Map06::special07() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(17, 1, STRING["maps.poof"]));
+ g_maps->_mapPos.x = 10;
+ g_maps->_mapPos.y = 11;
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void Map06::special09() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map06.banner"]));
+}
+
+void Map06::special10() {
+ g_maps->_mapPos.x++;
+ g_globals->_encounters.execute();
+}
+
+void Map06::special13() {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+ _data[VAL3]++;
+
+ int monsterCount = getRandomNumber(5);
+
+ enc._levelIndex = 20;
+ int id1 = MONSTER_ID1[g_maps->_mapPos.y];
+ int id2 = MONSTER_ID2[g_maps->_mapPos.y];
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, id2);
+
+ enc.execute();
+}
+
+void Map06::special26() {
+ if (_data[VAL3]) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(STRING["maps.map06.wizard"]));
+ } else {
+ g_globals->_treasure[6] = 224;
+ g_globals->_treasure[7] = 46;
+ g_globals->_treasure[4] = 237;
+ g_globals->_treasure[5] = getRandomNumber(12) + 182;
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+}
+
+void Map06::slide() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(16, 1, STRING["maps.map06.slide"]));
+ _data[VAL2]++;
+
+ g_events->send("Game", GameMessage("UPDATE"));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map06.h b/engines/mm/mm1/maps/map06.h
index 66db9c7447b..45155dc0476 100644
--- a/engines/mm/mm1/maps/map06.h
+++ b/engines/mm/mm1/maps/map06.h
@@ -32,9 +32,46 @@ class Map06 : public Map {
typedef void (Map06:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special06();
+ void special07();
+ void special09();
+ void special10();
+ void special13();
+ void special26();
+ void slide();
- const SpecialFn SPECIAL_FN[1] = {
- &Map06::special00
+ const SpecialFn SPECIAL_FN[27] = {
+ &Map06::special00,
+ &Map06::special01,
+ &Map06::special02,
+ &Map06::special03,
+ &Map06::special04,
+ &Map06::special04,
+ &Map06::special06,
+ &Map06::special07,
+ &Map06::special07,
+ &Map06::special09,
+ &Map06::special10,
+ &Map06::special10,
+ &Map06::special10,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special13,
+ &Map06::special26
};
public:
Map06() : Map(6, "cave2", 0x1) {}
Commit: 080056428011c9aefa8eb50cd0b0b2e5c898ed70
https://github.com/scummvm/scummvm/commit/080056428011c9aefa8eb50cd0b0b2e5c898ed70
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: Added map 7
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map07.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 7048c2ce67b..b059858bdfd 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -959,4 +959,14 @@ maps:
acid: "SPLASH! A POOL OF ACID!"
button: "BUTTON ON THE WALL, PRESS IT (Y/N)?"
banner: "A BANNER READS:\nCORRIDOR OF ENDLESS ENCOUNTERS!"
- wizard: "A CRAZED WIZARD EXCLAIMS,\n""ENCOUNTER THE 13, WIN THE PRIZE!""
+ wizard: "A CRAZED WIZARD EXCLAIMS,\n""ENCOUNTER THE 13, WIN THE PRIZE!"""
+
+ map07:
+ do_not_disturb: "\n""DEMONS IN CONFERENCE, DO NOT DISTURB!"""
+ gate: "BRONZE GRATE REPELS YOU!"
+ pool: "GLOWING POOL, STEP IN (Y/N)?"
+ portal: "BLUE AND WHITE PORTAL, ENTER (Y/N)?"
+ stairs: "STAIRS GOING UP! TAKE THEM (Y/N)?"
+ reversal: "REVERSAL!"
+ toxic: "TOXIC!"
+ might: "THOSE WHO ARE WORTHY +4 MIGHT!"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 4192befe01e..dc9285873a5 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -71,6 +71,13 @@ enum CharFlags0 {
CHARFLAG0_ZAM_CLUE = 0x10
};
+enum CharFlags11 {
+ CHARFLAG11_1 = 1,
+ CHARFLAG11_2 = 2,
+ CHARFLAG11_4 = 4,
+ CHARFLAG11_GOT_MIGHT = 8
+};
+
class Inventory {
public:
struct Entry {
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 9795423013e..0e0946951c7 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -32,7 +32,9 @@ namespace MM1 {
#define TREASURE_COUNT 9
enum ItemId {
- SCROLL_ID = 231
+ VELLUM_SCROLL_ID = 231,
+ BRONZE_KEY_ID = 237,
+ DIAMOND_KEY_ID = 240
};
enum EnablementBit {
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 40eeda36580..129bf4cb78f 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -197,7 +197,7 @@ void Map05::showMessage(const Common::String &msg) {
bool Map05::hasScroll() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
const Character &c = g_globals->_party[i];
- if (c._equipped.indexOf(SCROLL_ID) != -1)
+ if (c._equipped.indexOf(VELLUM_SCROLL_ID) != -1)
return true;
}
@@ -209,8 +209,8 @@ bool Map05::addScroll() {
Character &c = g_globals->_party[i];
if (!c._backpack.full()) {
// Add item
- c._backpack.add(SCROLL_ID, 0);
- g_globals->_items.getItem(SCROLL_ID);
+ c._backpack.add(VELLUM_SCROLL_ID, 0);
+ g_globals->_items.getItem(VELLUM_SCROLL_ID);
return true;
}
}
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 87e04061a21..9b3664b10f4 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -29,13 +29,18 @@ namespace MM {
namespace MM1 {
namespace Maps {
+static const byte MONSTER_IDS1[5] = { 2, 4, 1, 6, 4 };
+static const byte MONSTER_IDS2[5] = { 2, 5, 2, 3, 3 };
+static const byte MONSTER_IDS3[6] = { 2, 3, 3, 8, 8, 8 };
+static const byte MONSTER_IDS4[6] = { 10, 9, 9, 7, 7, 7 };
+
void Map07::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 18; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[69 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +49,183 @@ void Map07::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
+
g_maps->clearSpecial();
+ int idx = getRandomNumber(5) - 1;
+ setMonsters(MONSTER_IDS1[idx], MONSTER_IDS2[idx]);
g_globals->_encounters.execute();
- */
}
void Map07::special00() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map07.stairs"],
+ []() {
+ g_maps->_mapPos = Common::Point(0, 15);
+ g_maps->changeMap(0xc03, 1);
+ }
+ ));
+}
+
+void Map07::special01() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map07.portal"],
+ []() {
+ g_maps->_mapPos = Common::Point(2, 7);
+ g_maps->changeMap(0x202, 1);
+ }
+ ));
+}
+
+void Map07::special02() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ const Character &c = g_globals->_party[i];
+
+ for (uint j = 0; j < c._equipped.size(); ++j) {
+ if (c._equipped[j]._id >= BRONZE_KEY_ID &&
+ c._equipped[j]._id <= DIAMOND_KEY_ID)
+ // Someone has a key
+ return;
+ }
+ }
+
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map07.gate"]));
+ g_maps->_mapPos.y--;
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void Map07::special03() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map07.do_not_disturb"]));
+}
+
+void Map07::special04() {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+
+ enc.clearMonsters();
+ for (int i = 0; i < 6; ++i)
+ enc.addMonster(MONSTER_IDS3[i], MONSTER_IDS4[i]);
+
+ for (int i = 6; i < 13; ++i)
+ enc.addMonster(1, 2);
+
+ enc.execute();
+}
+
+void Map07::special05() {
+ g_maps->clearSpecial();
+ setMonsters();
+ g_globals->_encounters.addMonster(9, 2);
+ g_globals->_encounters.execute();
+}
+
+void Map07::special07() {
+ g_maps->clearSpecial();
+ setMonsters();
+ g_globals->_encounters.addMonster(10, 4);
+ g_globals->_encounters.execute();
+}
+
+void Map07::special09() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ g_maps->clearSpecial();
+ setMonsters();
+
+ for (int i = 6; i < 10; ++i)
+ enc.addMonster(9, 2);
+ for (int i = 10; i < 13; ++i)
+ enc.addMonster(10, 4);
+ enc.addMonster(11, 4);
+ enc.execute();
+}
+
+void Map07::special11() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ g_maps->clearSpecial();
+ setMonsters();
+
+ for (int i = 6; i < 12; ++i)
+ enc.addMonster(11, 4);
+
+ enc.addMonster(9, 5);
+ enc.execute();
+}
+
+void Map07::special13() {
+ poolYN(
+ []() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._sex = (c._sex == MALE) ? FEMALE : MALE;
+ }
+
+ Sound::sound(SOUND_2);
+ Sound::sound(SOUND_3);
+ g_events->send(InfoMessage(0, 1, STRING["maps.map07.reversal"]));
+ }
+ );
+}
+
+void Map07::special14() {
+ applyCondition(POISONED);
+}
+
+void Map07::special15() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._flags[11] & CHARFLAG11_GOT_MIGHT)) {
+ c._flags[11] |= CHARFLAG11_GOT_MIGHT;
+ c._might._base = MIN((int)c._might._base + 4, 255);
+ }
+ }
+
+ Sound::sound(SOUND_2);
+ Sound::sound(SOUND_3);
+ g_events->send(InfoMessage(0, 1, STRING["maps.map07.might"]));
+}
+
+void Map07::special16() {
+ applyCondition(DISEASED);
+}
+
+void Map07::special17() {
+ poolYN([]() {
+ g_globals->_treasure[5] = getRandomNumber(12) + 24;
+ g_globals->_treasure[8] = 20;
+ g_events->addAction(KEYBIND_SEARCH);
+ });
+}
+
+void Map07::setMonsters(int id1, int id2) {
+ Game::Encounter &enc = g_globals->_encounters;
+ enc.clearMonsters();
+
+ for (int i = 0; i < 6; ++i)
+ enc.addMonster(id1, id2);
+
+ enc._flag = true;
+ enc._levelIndex = 48;
+}
+
+void Map07::poolYN(YNCallback callback) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(STRING["maps.map07.pool"], callback));
+}
+
+void Map07::applyCondition(Condition cond) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._condition & BAD_CONDITION))
+ c._condition = cond;
+ }
+
+ Sound::sound(SOUND_3);
+ send(InfoMessage(0, 1, STRING["maps.map07.toxic"]));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map07.h b/engines/mm/mm1/maps/map07.h
index 9fbf53c4bc0..f2b794c2341 100644
--- a/engines/mm/mm1/maps/map07.h
+++ b/engines/mm/mm1/maps/map07.h
@@ -23,6 +23,7 @@
#define MM1_MAPS_MAP07_H
#include "mm/mm1/maps/map.h"
+#include "mm/mm1/data/character.h"
namespace MM {
namespace MM1 {
@@ -32,9 +33,42 @@ class Map07 : public Map {
typedef void (Map07:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special07();
+ void special09();
+ void special11();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special17();
+ void setMonsters(int id1 = 10, int id2 = 1);
+ void poolYN(YNCallback callback);
+ void applyCondition(Condition cond);
- const SpecialFn SPECIAL_FN[1] = {
- &Map07::special00
+ const SpecialFn SPECIAL_FN[18] = {
+ &Map07::special00,
+ &Map07::special01,
+ &Map07::special02,
+ &Map07::special03,
+ &Map07::special04,
+ &Map07::special05,
+ &Map07::special05,
+ &Map07::special07,
+ &Map07::special07,
+ &Map07::special09,
+ &Map07::special09,
+ &Map07::special11,
+ &Map07::special11,
+ &Map07::special13,
+ &Map07::special14,
+ &Map07::special15,
+ &Map07::special16,
+ &Map07::special17
};
public:
Map07() : Map(7, "cave3", 0xC01) {}
Commit: 9215f84836aae6321b289193e2e1a648ad0ebefa
https://github.com/scummvm/scummvm/commit/9215f84836aae6321b289193e2e1a648ad0ebefa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: Implemented access code view for map 8
Changed paths:
A engines/mm/mm1/views/maps/access_code.cpp
A engines/mm/mm1/views/maps/access_code.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map08.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b059858bdfd..19e6caaabb0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -814,8 +814,10 @@ monster_spells:
10: "IS AFFECTED"
maps:
- sign: "A SIGN ABOVE THE DOOR READS:\n"
poof: "POOF!"
+ sign: "A SIGN ABOVE THE DOOR READS:\n"
+ stairs_up: "STAIRS GOING UP! TAKE THEM (Y/N)?"
+ stairs_down: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
map00:
blacksmith: """B AND B BLACKSMITHING"""
@@ -834,7 +836,6 @@ maps:
training_inside: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
leprechaun: "A TENACIOUS LEPRECHAUN APPEARS SAYING,\n""TRAVELING THE ROADS IS QUITE DANGEROUS\nSAVE FOR THE STRONG AND COURAGEOUS,\nONLY 1 GEM YOU LOSE AND I'LL SEND YOU\nTO THE TOWN YOU CHOOSE.""\n\n'ESC' TO GO BACK WHICH TOWN (1-5)?"
- stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
statue: "THERE IS A STATUE HERE. SEARCH IT (Y/N)?"
trapdoor: "TRAP DOOR!"
levitate: ", LEVITATION SAVES YOU!"
@@ -858,7 +859,6 @@ maps:
males_drained: "MALES ARE DRAINED!"
passage_outside: "PASSAGE OUTSIDE, EXIT (Y/N)?"
secret: "A SENSUOUS FEMALE VOICE SPEAKS FROM\nWITHIN AN INTOXICATING MIST,\n""YOU'VE DISCOVERED MY SECRET!"""
- stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
zam0: "NOTE: ZAM 12,2"
zam1: """I AM ZAM, ASTRAL BROTHER OF ZOM AND\nONLY LIVING MALE RESIDING IN PORTSMITH\n"
zam2: "MY CLUE IS C-15"""
@@ -908,7 +908,6 @@ maps:
temple_inside: "BRIGHT LIGHTS SWIRL THROUGHOUT THE ROOM.A HORRIFYING VOICE SHRIEKS,\n""NEED HELP (Y/N)?"""
training_inside: "SEVERAL EMPTY SUITS OF ARMOR APPROACH\nASKING, ""NEED TRAINING (Y/N)?"""
- stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
telgoran1: "AN ELF DRESSED IN ROBES APPROACHES...\n\n"
@@ -937,14 +936,12 @@ maps:
guards: "TOWN GUARDS: YOU'RE UNDER ARREST!\n\nA)ATTACK B)BRIBE C)RUN D)SURRENDER"
passage_outside: "PASSAGE OUTSIDE, EXIT (Y/N)?"
sentence: "HIGH COURT SENTENCE: YEARS= "
- stairs: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
treasure: "TOWN TREASURE, STEAL (Y/N)?"
map05:
arena: """THE ARENA"""
arena_inside: "AROUND THE ROOM THERE ARE SEVERAL\nBALCONIES FILLED WITH CHEERING PEASANTS\nA MAN ASKS ""WILL YOU PARTICIPATE (Y/N)?"""
portal: "A SHIMMERING BLUE AND WHITE PORTAL\nAPPEARS! ENTER (Y/N)?"
- stairs: "STAIRS GOING UP! TAKE THEM (Y/N)?"
message1:"SCRAWLED ON THE WALL, A MESSAGE READS:\n"
message2: "THE JAIL ABOVE HAS MANY CELLS."
message3: "DON'T TURN AROUND!"
@@ -966,7 +963,14 @@ maps:
gate: "BRONZE GRATE REPELS YOU!"
pool: "GLOWING POOL, STEP IN (Y/N)?"
portal: "BLUE AND WHITE PORTAL, ENTER (Y/N)?"
- stairs: "STAIRS GOING UP! TAKE THEM (Y/N)?"
reversal: "REVERSAL!"
toxic: "TOXIC!"
might: "THOSE WHO ARE WORTHY +4 MIGHT!"
+
+ map08:
+ alarm: "ALARM!"
+ bad_code: """IMPROPER ACCESS CODE!"""
+ dancing_lights: "DANCING LIGHTS FLICKER AND CRACKEL IN\nTHE AREA IN FRONT OF YOU!"
+ enter_code: "COVERED WITH FLASHING LIGHTS THE WALL\nSPEAKS: ""PLEASE ENTER ACCESS CODE:""\n"
+ good_code: """THANK YOU, FIELDS DEACTIVATED."""
+ zap: "ZAP!"
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index a4b3e04df7a..f36811148cd 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -170,7 +170,7 @@ void Map00::special08() {
void Map00::special09() {
Sound::sound(SOUND_2);
send(InfoMessage(
- STRING["maps.map00.stairs"],
+ STRING["maps.stairs_down"],
[]() {
g_maps->changeMap(0xa11, 1);
}
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index b0cf630fdb5..4c2df49dea4 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -157,7 +157,7 @@ void Map03::special08() {
void Map03::special09() {
Sound::sound(SOUND_2);
send(InfoMessage(
- STRING["maps.map01.stairs"],
+ STRING["maps.stairs_down"],
[]() {
g_maps->_mapPos = Common::Point(14, 0);
g_maps->changeMap(5, 1);
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index ad93de343fe..616bb126e07 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -156,7 +156,7 @@ void Map04::special09() {
Sound::sound(SOUND_2);
send(InfoMessage(
- STRING["maps.map04.stairs"],
+ STRING["maps.stairs_down"],
[]() {
g_maps->_mapPos.x = 0;
g_maps->_mapPos.y = 7;
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 129bf4cb78f..68203c108e7 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -56,7 +56,7 @@ void Map05::special() {
void Map05::special00() {
Sound::sound(SOUND_2);
send(InfoMessage(
- STRING["maps.map05.stairs"],
+ STRING["maps.stairs_up"],
[]() {
g_maps->changeMap(0x604, 1);
}
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 9b3664b10f4..9292687aa14 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -59,7 +59,7 @@ void Map07::special() {
void Map07::special00() {
Sound::sound(SOUND_2);
send(InfoMessage(
- STRING["maps.map07.stairs"],
+ STRING["maps.stairs_up"],
[]() {
g_maps->_mapPos = Common::Point(0, 15);
g_maps->changeMap(0xc03, 1);
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 173dcda6d3e..5ae09b3fbd8 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -29,6 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 163
+
void Map08::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
@@ -36,7 +38,6 @@ void Map08::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[75 + i]) {
-
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,16 +45,66 @@ void Map08::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (g_maps->_mapPos.x == 0 || g_maps->_mapPos.x == 15) {
+ g_globals->_encounters.execute();
+ } else {
+ g_globals->_treasure[6] = getRandomNumber(150) + 100;
+ g_globals->_treasure[8] = getRandomNumber(4);
+ g_events->addAction(KEYBIND_SEARCH);
+ }
}
void Map08::special00() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->_mapPos = Common::Point(15, 7);
+ g_maps->changeMap(0xb1a, 1);
+ }
+ ));
+}
+
+void Map08::special01() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->_mapPos = Common::Point(0, 14);
+ g_maps->changeMap(0xa00, 2);
+ }
+ ));
+}
+
+void Map08::special02() {
+ if (_data[VAL1]) {
+ g_events->addView("AccessCode");
+ } else {
+ checkPartyDead();
+ }
}
+void Map08::special04() {
+}
+
+void Map08::special05() {
+}
+
+void Map08::special06() {
+}
+
+void Map08::special08() {
+}
+
+void Map08::special20() {
+}
+
+
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map08.h b/engines/mm/mm1/maps/map08.h
index 670cb6beddf..00d6f5dcf28 100644
--- a/engines/mm/mm1/maps/map08.h
+++ b/engines/mm/mm1/maps/map08.h
@@ -32,9 +32,39 @@ class Map08 : public Map {
typedef void (Map08:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special04();
+ void special05();
+ void special06();
+ void special08();
+ void special20();
- const SpecialFn SPECIAL_FN[1] = {
- &Map08::special00
+ const SpecialFn SPECIAL_FN[24] = {
+ &Map08::special00,
+ &Map08::special01,
+ &Map08::special02,
+ &Map08::special02,
+ &Map08::special04,
+ &Map08::special05,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special08,
+ &Map08::special08,
+ &Map08::special08,
+ &Map08::special08,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special06,
+ &Map08::special20,
+ &Map08::special20,
+ &Map08::special20,
+ &Map08::special20
};
public:
Map08() : Map(8, "cave4", 0x202) {}
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
new file mode 100644
index 00000000000..5210e8b417c
--- /dev/null
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -0,0 +1,124 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/access_code.h"
+#include "mm/mm1/maps/map08.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define MAX_CODE_LENGTH 10
+#define CODE_OFFSET 147
+#define VAL1 163
+#define VAL2 408
+
+static const byte OFFSETS1[8] = { 146, 98, 150, 102, 153, 105, 157, 109 };
+static const byte OFFSETS2[8] = { 130, 82, 134, 86, 137, 89, 141, 93 };
+
+AccessCode::AccessCode() : TextView("AccessCode") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool AccessCode::msgFocus(const FocusMessage &msg) {
+ _code = "";
+ Sound::sound(SOUND_2);
+ return TextView::msgFocus(msg);
+}
+
+void AccessCode::draw() {
+ clearSurface();
+
+ writeString(0, 1, STRING["maps.map08.dancing_lights"]);
+ writeString(16, 3, _code);
+ for (uint i = 0; i < (MAX_CODE_LENGTH - _code.size()); ++i)
+ writeChar('.');
+}
+
+bool AccessCode::msgKeypress(const KeypressMessage &msg) {
+ if (!isDelayActive()) {
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ codeEntered();
+ } else if (msg.keycode == Common::KEYCODE_SPACE ||
+ (msg.keycode >= Common::KEYCODE_0 &&
+ msg.keycode <= Common::KEYCODE_z)) {
+ _code += toupper(msg.ascii);
+ if (_code.size() == MAX_CODE_LENGTH)
+ codeEntered();
+ }
+ }
+
+ return true;
+}
+
+void AccessCode::codeEntered() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Common::String properCode;
+ for (int i = 0; i < 10 && map[CODE_OFFSET + i]; ++i)
+ properCode += map[CODE_OFFSET + i] + 0x1f;
+
+ if (_code == properCode)
+ correctCode();
+ else
+ incorrectCode();
+}
+
+void AccessCode::correctCode() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Sound::sound(SOUND_2);
+ clearSurface();
+ writeString(0, 1, STRING["maps.map08.good_code"]);
+
+ map[VAL1] = 0;
+ for (int i = 0; i < 8; ++i)
+ map._walls[OFFSETS1[i]] ^= 4;
+ for (int i = 0; i < 8; ++i)
+ map._walls[OFFSETS2[i]] ^= 0x40;
+ map._walls[119] ^= 0x10;
+ map._walls[120] ^= 1;
+}
+
+void AccessCode::incorrectCode() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Sound::sound(SOUND_2);
+ clearSurface();
+ writeString(0, 1, STRING["maps.map08.bad_code"]);
+
+ if (map[VAL2] != 2 && map[VAL2] < 20) {
+ g_maps->_mapPos.y--;
+ g_events->send("Game", GameMessage("UPDATE"));
+ return;
+ } else if (map[VAL2] != 2) {
+ map[MM1::Maps::MAP_31] = 10;
+ }
+
+ writeString(17, 2, STRING["maps.map08.alarm"]);
+ Sound::sound(SOUND_3);
+ delaySeconds(2);
+}
+
+} // namespace Spells
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/access_code.h b/engines/mm/mm1/views/maps/access_code.h
new file mode 100644
index 00000000000..922184fd6dc
--- /dev/null
+++ b/engines/mm/mm1/views/maps/access_code.h
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_ACCESS_CODE_H
+#define MM1_VIEWS_MAPS_ACCESS_CODE_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class AccessCode : public TextView {
+private:
+ Common::String _code;
+
+ /**
+ * Called when the code has been entered
+ */
+ void codeEntered();
+
+ /**
+ * Correct code entered
+ */
+ void correctCode();
+
+ /**
+ * Incorrect code entered
+ */
+ void incorrectCode();
+
+public:
+ AccessCode();
+ virtual ~AccessCode() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 308fb9f9d02..588e3ebc5ab 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -50,6 +50,7 @@ MODULE_OBJS := \
mm1/views/locations/tavern.o \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
+ mm1/views/maps/access_code.o \
mm1/views/maps/arrested.o \
mm1/views/maps/resistances.o \
mm1/views/spells/spell_view.o \
Commit: 313d468ff064596786cfb02f1042e46357f8229c
https://github.com/scummvm/scummvm/commit/313d468ff064596786cfb02f1042e46357f8229c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: Add remainder of map 8
Changed paths:
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map08.h
engines/mm/mm1/views/maps/access_code.cpp
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 5ae09b3fbd8..857ddcd2cda 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -52,9 +52,7 @@ void Map08::special() {
if (g_maps->_mapPos.x == 0 || g_maps->_mapPos.x == 15) {
g_globals->_encounters.execute();
} else {
- g_globals->_treasure[6] = getRandomNumber(150) + 100;
- g_globals->_treasure[8] = getRandomNumber(4);
- g_events->addAction(KEYBIND_SEARCH);
+ addTreasure();
}
}
@@ -89,21 +87,49 @@ void Map08::special02() {
}
void Map08::special04() {
+ g_maps->_mapPos = Common::Point(15, 9);
+ g_events->send("Game", GameMessage("UPDATE"));
}
void Map08::special05() {
+ g_maps->_mapPos = Common::Point(0, 9);
+ g_events->send("Game", GameMessage("UPDATE"));
}
void Map08::special06() {
+ if (_data[VAL1]) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._hpBase /= 2;
+
+ send(InfoMessage(18, 2, STRING["maps.map08.zap"]));
+ Sound::sound(SOUND_3);
+ } else {
+ checkPartyDead();
+ }
}
void Map08::special08() {
+ if (_data[VAL1]) {
+ send(InfoMessage(0, 1, STRING["maps.map08.dancing_lights"]));
+ Sound::sound(SOUND_3);
+ } else {
+ checkPartyDead();
+ }
}
void Map08::special20() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[5] = getRandomNumber(48);
+ g_globals->_treasure[1] = 1;
+ g_globals->_treasure[2] = 6;
+ addTreasure();
}
-
+void Map08::addTreasure() {
+ g_globals->_treasure[6] = getRandomNumber(150) + 100;
+ g_globals->_treasure[8] = getRandomNumber(4);
+ g_events->addAction(KEYBIND_SEARCH);
+}
} // namespace Maps
} // namespace MM1
diff --git a/engines/mm/mm1/maps/map08.h b/engines/mm/mm1/maps/map08.h
index 00d6f5dcf28..a5f732717ba 100644
--- a/engines/mm/mm1/maps/map08.h
+++ b/engines/mm/mm1/maps/map08.h
@@ -39,6 +39,7 @@ private:
void special06();
void special08();
void special20();
+ void addTreasure();
const SpecialFn SPECIAL_FN[24] = {
&Map08::special00,
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
index 5210e8b417c..4d1594e9f9b 100644
--- a/engines/mm/mm1/views/maps/access_code.cpp
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -50,7 +50,7 @@ bool AccessCode::msgFocus(const FocusMessage &msg) {
void AccessCode::draw() {
clearSurface();
- writeString(0, 1, STRING["maps.map08.dancing_lights"]);
+ writeString(0, 1, STRING["maps.map08.enter_code"]);
writeString(16, 3, _code);
for (uint i = 0; i < (MAX_CODE_LENGTH - _code.size()); ++i)
writeChar('.');
Commit: 9965b1587761fe83318a8a9f837b7b6902bfd1e8
https://github.com/scummvm/scummvm/commit/9965b1587761fe83318a8a9f837b7b6902bfd1e8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: Implementing map 9
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map09.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 19e6caaabb0..3a805cc73a4 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -974,3 +974,20 @@ maps:
enter_code: "COVERED WITH FLASHING LIGHTS THE WALL\nSPEAKS: ""PLEASE ENTER ACCESS CODE:""\n"
good_code: """THANK YOU, FIELDS DEACTIVATED."""
zap: "ZAP!"
+
+ map09:
+ accuracy: "THE PRISM OF PRECISION GRANTS THOSE\nWHO ARE WORTHY +4 ACCURACY!"
+ agility: "THE FLAME OF AGILITY GRANTS THOSE WHO\nARE WORTHY +4 SPEED!"
+ corak_was_here: "CORAK WAS HERE"
+ levitation: "LEVITATION SAVED YOU."
+ message: "BEHIND AN OLD TAPESTRY, A MESSAGE\nETCHED IN GOLD READS: YICU2ME3"
+ passage_outside: "A CAVERNOUS PASSAGE, TAKE IT (Y/N)?"
+ pit: "A PIT OF POISONOUS SPIKES!\n"
+ portal: "BLUE AND WHITE PORTAL, ENTER (Y/N)?"
+ protection: "PROTECTION SAVED YOU."
+ psychic_blast: "PSYCHIC BLAST!\n"
+ scrawl: "SCRAWLED IN STONE:\nCHARACTER #1 LEADS THE WAY.\nBEWARE, TRAPS ABOUND!"
+ shrine1: "THE SHRINE OF OKZAR, PRAY (Y/N)?"
+ shrine2: "YOUR LEADER IS OF CLEAR MIND."
+ shrine3: "YOUR LEADER IS INCONSISTENT. BEGONE!"
+ stalactites: "STALACTITES SHOWER THE PARTY!"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index dc9285873a5..95a058d122c 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -71,11 +71,17 @@ enum CharFlags0 {
CHARFLAG0_ZAM_CLUE = 0x10
};
+enum CharFlags5 {
+ CHARFLAG5_8 = 8
+};
+
enum CharFlags11 {
CHARFLAG11_1 = 1,
CHARFLAG11_2 = 2,
CHARFLAG11_4 = 4,
- CHARFLAG11_GOT_MIGHT = 8
+ CHARFLAG11_GOT_MIGHT = 8,
+ CHARFLAG11_GOT_ACCURACY = 0x10,
+ CHARFLAG11_GOT_SPEED = 0x20
};
class Inventory {
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 857ddcd2cda..41f4e1eac82 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -46,7 +46,6 @@ void Map08::special() {
}
}
- // All other cells on the map are encounters
g_maps->clearSpecial();
if (g_maps->_mapPos.x == 0 || g_maps->_mapPos.x == 15) {
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index 1c585810ebc..5b34eed5df8 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -29,14 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+static const byte MAP_DEST_X[4] = { 8, 15, 15, 7 };
+static const byte MAP_DEST_Y[4] = { 5, 1, 0, 0 };
+static const uint16 MAP_DEST_ID[4] = { 0x604, 0x51b, 0x601, 0xa00 };
+
void Map09::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 28; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[79 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +47,164 @@ void Map09::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map09::special00() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0x802, 1);
+ }
+ ));
+}
+
+void Map09::special01() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map09.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(0, 0);
+ g_maps->changeMap(0xf05, 3);
+ }
+ ));
+}
+
+void Map09::special02() {
+ portal(0);
+}
+
+void Map09::special03() {
+ portal(1);
+}
+
+void Map09::special04() {
+ portal(2);
+}
+
+void Map09::special05() {
+ portal(3);
+}
+
+void Map09::special06() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._flags[11] & CHARFLAG11_GOT_ACCURACY)) {
+ c._flags[11] |= CHARFLAG11_GOT_ACCURACY;
+ c._might._base = MIN((int)c._accuracy._base + 4, 255);
+ }
+ }
+
+ Sound::sound(SOUND_2);
+ g_events->send(InfoMessage(0, 1, STRING["maps.map07.accuracy"]));
+}
+
+void Map09::special07() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._flags[11] & CHARFLAG11_GOT_SPEED)) {
+ c._flags[11] |= CHARFLAG11_GOT_SPEED;
+ c._might._base = MIN((int)c._speed._base + 4, 255);
+ }
+ }
+
+ Sound::sound(SOUND_2);
+ g_events->send(InfoMessage(0, 1, STRING["maps.map07.speed"]));
+}
+
+void Map09::special08() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[5] |= CHARFLAG5_8;
+ }
+
+ const Character &leader = g_globals->_party[0];
+ Sound::sound(SOUND_2);
+
+ if (leader._alignment == leader._alignmentInitial) {
+ send(InfoMessage(
+ 0, 1, STRING["maps.map09.shrine1"],
+ 0, 2, STRING["maps.map09.shrine2"]
+ ));
+
+ g_globals->_treasure[5] = getRandomNumber(26) + 120;
+ g_globals->_treasure[6] = 120;
+ g_events->addAction(KEYBIND_SEARCH);
+
+ } else {
+ send(InfoMessage(
+ 0, 1, STRING["maps.map09.shrine1"],
+ 0, 2, STRING["maps.map09.shrine3"]
+ ));
+
+ // TODO: Check this is right. Original set y twice
+ g_maps->_mapPos = Common::Point(5, 13);
+ g_maps->changeMap(0x201, 3);
+ }
+}
+
+void Map09::special09() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map09.stalactities"]));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._hpBase /= 2;
+ }
+}
+
+void Map09::special14() {
+ g_maps->clearSpecial();
+ Sound::sound(SOUND_2);
+
+ if (g_globals->_activeSpells._s.levitate) {
+ send(InfoMessage(
+ 0, 1, STRING["maps.map09.map"],
+ 0, 2, STRING["maps.map09.levitation"]
+ ));
+ } else {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!g_globals->_activeSpells._s.poison &&
+ !(c._condition & BAD_CONDITION))
+ c._condition = POISONED;
+ c._hpBase /= 2;
+ }
+
+ send(InfoMessage(
+ 0, 1, STRING["maps.map09.map"]
+ ));
+ }
+}
+
+void Map09::special18() {
+}
+
+void Map09::special25() {
+}
+
+void Map09::special26() {
+}
+
+void Map09::special27() {
+}
+
+void Map09::portal(int index) {
+ _portalIndex = index;
+
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ STRING["maps.map09.portal"],
+ []() {
+ int index = static_cast<Map09 *>(g_maps->_currentMap)->_portalIndex;
+ g_maps->_mapPos = Common::Point(MAP_DEST_X[index], MAP_DEST_Y[index]);
+ g_maps->changeMap(MAP_DEST_ID[index], 1);
+ }
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map09.h b/engines/mm/mm1/maps/map09.h
index 54749c57dd3..7cc4e09473c 100644
--- a/engines/mm/mm1/maps/map09.h
+++ b/engines/mm/mm1/maps/map09.h
@@ -31,10 +31,54 @@ namespace Maps {
class Map09 : public Map {
typedef void (Map09:: *SpecialFn)();
private:
+ int _portalIndex = 0;
+
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special14();
+ void special18();
+ void special25();
+ void special26();
+ void special27();
+ void portal(int index);
- const SpecialFn SPECIAL_FN[1] = {
- &Map09::special00
+ const SpecialFn SPECIAL_FN[28] = {
+ &Map09::special00,
+ &Map09::special01,
+ &Map09::special02,
+ &Map09::special03,
+ &Map09::special04,
+ &Map09::special05,
+ &Map09::special06,
+ &Map09::special07,
+ &Map09::special08,
+ &Map09::special09,
+ &Map09::special09,
+ &Map09::special09,
+ &Map09::special09,
+ &Map09::special09,
+ &Map09::special14,
+ &Map09::special14,
+ &Map09::special14,
+ &Map09::special14,
+ &Map09::special18,
+ &Map09::special18,
+ &Map09::special18,
+ &Map09::special18,
+ &Map09::special18,
+ &Map09::special18,
+ &Map09::special18,
+ &Map09::special25,
+ &Map09::special26,
+ &Map09::special27
};
public:
Map09() : Map(9, "cave5", 0x5) {}
Commit: a99b52bbb1d45b0aa53326f8b61fc939385caeda
https://github.com/scummvm/scummvm/commit/a99b52bbb1d45b0aa53326f8b61fc939385caeda
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:20+01:00
Commit Message:
MM: MM1: In progress map 10, added SoundMessage subclass
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map10.h
engines/mm/mm1/messages.h
engines/mm/mm1/views/game_messages.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3a805cc73a4..e3ff8f82a25 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -911,8 +911,8 @@ maps:
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
telgoran1: "AN ELF DRESSED IN ROBES APPROACHES...\n\n"
- telgoran2: """FRIENDS, I AM TELGORAN. THIS SCROLL YOU\nHAVE BROUGHT ME WILL BE VERY HELPFUL',0Dh,'(+2500 EXP) HERE'S 1500 GOLD FOR YOUR\nSERVICES. I'LL TELL YOU A SECRET, IF\nTREASURE IS WHAT YOU WANT..."""
- telgoran3: """THE BROTHERS YOU MUST FIND...',0Dh,'PORTSMITH AND ALGARY ARE COMBINED."""
+ telgoran2: """FRIENDS, I AM TELGORAN. THIS SCROLL YOU\nHAVE BROUGHT ME WILL BE VERY HELPFUL"Dh,'(+2500 EXP) HERE'S 1500 GOLD FOR YOUR\nSERVICES. I'LL TELL YOU A SECRET, IF\nTREASURE IS WHAT YOU WANT..."""
+ telgoran3: """THE BROTHERS YOU MUST FIND..."Dh,'PORTSMITH AND ALGARY ARE COMBINED."""
telgoran4: """YOU'RE NOT THE COURIERS!"""
map04:
@@ -991,3 +991,14 @@ maps:
shrine2: "YOUR LEADER IS OF CLEAR MIND."
shrine3: "YOUR LEADER IS INCONSISTENT. BEGONE!"
stalactites: "STALACTITES SHOWER THE PARTY!"
+
+ map10:
+ levitation: "LEVITATION SAVED YOU."
+ passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ pit: "JAGGED SLIME PIT! "
+ poof: "POOF! YOU'VE BEEN TELEPORTED..."
+ ranalou1: """I'M THE WIZARD RANALOU. ARE YOU HERE TO\nUSE THE PORTALS (Y/N)?"""
+ ranalou2: """GOOD! INSIDE THIS ROOM ARE 6 PORTALS,\nEACH OF WHICH LEADS TO A CASTLE. THE\nSTATUE OF JUDGEMENT REQUIRES YOU TO FIND\nONE PRISONER FROM EACH OF THESE CASTLES\nBEFORE YOU MAY BE FOUND WORTHY."""
+ ranalou3: """THEN BEGONE!"""
+ sign1: "A SIGN:\n\nEXPERIMENT IN PROGRESS, DO NOT ENTER!"
+ sign2: "A SIGN:\n\nAUTHORIZED PERSONNEL ONLY! KEEP OUT."
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 95a058d122c..38cda7b694b 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -71,6 +71,10 @@ enum CharFlags0 {
CHARFLAG0_ZAM_CLUE = 0x10
};
+enum CharFlags1 {
+ CHARFLAG1_1 = 1
+};
+
enum CharFlags5 {
CHARFLAG5_8 = 8
};
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index 5b34eed5df8..59e4974bbb2 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -182,15 +182,47 @@ void Map09::special14() {
}
void Map09::special18() {
+ if (g_globals->_activeSpells._s.psychic_protection) {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(
+ 0, 1, STRING["maps.map09.psychic_blast"],
+ 0, 2, STRING["maps.map09.protection"]
+ ));
+ } else {
+ g_globals->_currCharacter = &g_globals->_party[
+ getRandomNumber(g_globals->_party.size()) - 1
+ ];
+
+
+ if (!(g_globals->_currCharacter->_condition & BAD_CONDITION)) {
+ // Chosen character is okay, so blast them
+ g_globals->_currCharacter->_condition = BAD_CONDITION | DEAD;
+ } else {
+ // Chosen character is disabled, so instead
+ // remove the SP from all members of the party
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ g_globals->_currCharacter->_sp._current = 0;
+ }
+ }
+
+ g_globals->_encounters.execute();
+ }
}
void Map09::special25() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map09.scrawl"]));
}
void Map09::special26() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map09.corak_was_here"]));
}
void Map09::special27() {
+ Sound::sound(SOUND_2);
+ send(InfoMessage(0, 1, STRING["maps.map09.message"]));
}
void Map09::portal(int index) {
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index 27c4e047af2..2d86c29ef82 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -29,13 +29,27 @@ namespace MM {
namespace MM1 {
namespace Maps {
+static const byte MAP_DEST_X[15] = {
+ 7, 7, 3, 3, 7, 13, 1, 7, 9, 13, 12, 1, 8, 12, 4
+};
+static const byte MAP_DEST_Y[15] = {
+ 3, 14, 7, 7, 12, 8, 13, 3, 0, 7, 2, 14, 13, 7, 7
+};
+static const uint16 MAP_DEST_ID[15] = {
+ 0x706, 0x107, 0xb07, 0x508, 0xf08, 0xa11, 0xa11, 1,
+ 0xc01, 0x202, 0x604, 0xc03, 0x203, 0x802, 0xb1a
+};
+static const byte MAP_DEST_SECTION[15] = {
+ 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
void Map10::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[85 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +58,98 @@ void Map10::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map10::special00() {
+ send(SoundMessage(
+ STRING["maps.map10.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(0, 7);
+ g_maps->changeMap(0x101, 2);
+ }
+ ));
+}
+
+void Map10::special01() {
+ send(SoundMessage(
+ STRING["maps.map10.ranalou1"],
+ [](const Common::KeyState &ks) {
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->send(InfoMessage(STRING["maps.map10.ranalou2"]));
+ Sound::sound(SOUND_3);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._flags[1] |= CHARFLAG1_1;
+
+ g_maps->clearSpecial();
+
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->send(SoundMessage(STRING["maps.map10.ranalou3"]));
+ g_maps->_mapPos = Common::Point(15, 0);
+ g_events->send("Game", GameMessage("UPDATE"));
+ }
+ }
+ ));
+}
+
+void Map10::special02() {
+ send(SoundMessage(STRING["maps.map10.poof"]));
+ int idx = g_maps->_mapPos.x;
+ g_maps->_mapPos = Common::Point(MAP_DEST_X[idx], MAP_DEST_Y[idx]);
+ g_maps->changeMap(MAP_DEST_ID[idx], MAP_DEST_SECTION[idx]);
+}
+
+void Map10::special17() {
+ g_maps->_mapPos.y++;
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void Map10::special18() {
+ g_maps->_mapPos.x++;
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void Map10::special19() {
+ g_maps->_mapPos.x--;
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void Map10::special20() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[5] = 252;
+ g_globals->_treasure[8] = 20;
+ g_globals->_treasure[2] = 6;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map10::special23() {
+
+}
+
+void Map10::special29() {
+}
+
+void Map10::special30() {
+}
+
+void Map10::special31() {
+}
+
+void Map10::special32() {
+}
+
+void Map10::special33() {
+}
+
+void Map10::reduceHP() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ g_globals->_currCharacter->_hpBase /= 2;
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map10.h b/engines/mm/mm1/maps/map10.h
index fc0fdf88e88..52114c8185e 100644
--- a/engines/mm/mm1/maps/map10.h
+++ b/engines/mm/mm1/maps/map10.h
@@ -32,9 +32,55 @@ class Map10 : public Map {
typedef void (Map10:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special17();
+ void special18();
+ void special19();
+ void special20();
+ void special23();
+ void special29();
+ void special30();
+ void special31();
+ void special32();
+ void special33();
+ void reduceHP();
- const SpecialFn SPECIAL_FN[1] = {
- &Map10::special00
+ const SpecialFn SPECIAL_FN[34] = {
+ &Map10::special00,
+ &Map10::special01,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special02,
+ &Map10::special17,
+ &Map10::special18,
+ &Map10::special19,
+ &Map10::special20,
+ &Map10::special20,
+ &Map10::special20,
+ &Map10::special23,
+ &Map10::special23,
+ &Map10::special23,
+ &Map10::special23,
+ &Map10::special23,
+ &Map10::special23,
+ &Map10::special29,
+ &Map10::special30,
+ &Map10::special31,
+ &Map10::special32,
+ &Map10::special33
};
public:
Map10() : Map(10, "cave6", 0x51B) {}
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 5b6abbd39ed..a2ba2522970 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -99,6 +99,7 @@ struct InfoMessage : public Message {
YNCallback _ynCallback = nullptr;
KeyCallback _keyCallback = nullptr;
bool _largeMessage = false;
+ bool _sound = false;
InfoMessage();
InfoMessage(const Common::String &str);
@@ -123,6 +124,40 @@ struct InfoMessage : public Message {
KeyCallback keyCallback);
};
+struct SoundMessage : public InfoMessage {
+public:
+ SoundMessage() : InfoMessage() { _sound = true; }
+ SoundMessage(const Common::String &str) :
+ InfoMessage(0, 1, str) { _sound = true; }
+ SoundMessage(int x, int y, const Common::String &str) :
+ InfoMessage(x, y, str) { _sound = true; }
+ SoundMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2) :
+ InfoMessage(x1, y1, str1, x2, y2, str2) { _sound = true; }
+
+ SoundMessage(const Common::String &str,
+ YNCallback ynCallback) :
+ InfoMessage(0, 1, str, ynCallback) { _sound = true; }
+ SoundMessage(int x, int y, const Common::String &str,
+ YNCallback ynCallback) :
+ InfoMessage(x, y, str, ynCallback) { _sound = true; }
+ SoundMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2,
+ YNCallback ynCallback) :
+ InfoMessage(x1, y1, str1, x2, y2, str2, ynCallback) { _sound = true; }
+
+ SoundMessage(const Common::String &str,
+ KeyCallback keyCallback) :
+ InfoMessage(0, 1, str, keyCallback) { _sound = true; }
+ SoundMessage(int x, int y, const Common::String &str,
+ KeyCallback keyCallback) :
+ InfoMessage(x, y, str, keyCallback) { _sound = true; }
+ SoundMessage(int x1, int y1, const Common::String &str1,
+ int x2, int y2, const Common::String &str2,
+ KeyCallback keyCallback) :
+ InfoMessage(x1, y1, str1, x2, y2, str2, keyCallback) { _sound = true; }
+};
+
enum LocationType {
LOC_TRAINING = 0, LOC_MARKET = 1, LOC_TEMPLE = 2,
LOC_BLACKSMITH = 3, LOC_TAVERN = 4
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 0e9652c95b2..4992839d64b 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -22,6 +22,7 @@
#include "common/util.h"
#include "mm/mm1/views/game_messages.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -68,6 +69,9 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
else
_bounds = getLineBounds(21, 24);
+ if (msg._sound)
+ Sound::sound(SOUND_2);
+
redraw();
return true;
}
Commit: 9d75df5ed37855a9d8789222af8a7bd618be3bb3
https://github.com/scummvm/scummvm/commit/9d75df5ed37855a9d8789222af8a7bd618be3bb3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:21+01:00
Commit Message:
MM: MM1: Change prior map classes to use new SoundMessage
Changed paths:
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map06.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map_town.cpp
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index f36811148cd..478c523e31f 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -61,8 +61,6 @@ void Map00::special00() {
}
void Map00::special01() {
- Sound::sound(SOUND_2);
-
Common::String line2;
int x = 5;
@@ -79,7 +77,7 @@ void Map00::special01() {
break;
}
- send(InfoMessage(
+ send(SoundMessage(
2, 0, STRING["maps.sign"],
x, 1, line2
));
@@ -94,8 +92,7 @@ void Map00::special03() {
}
void Map00::special04() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map00.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(10, 10);
@@ -117,8 +114,7 @@ void Map00::special07() {
}
void Map00::special08() {
- Sound::sound(SOUND_2);
- InfoMessage msg(
+ SoundMessage msg(
STRING["maps.map00.leprechaun"],
[](const Common::KeyState &keyState) {
Maps &maps = *g_maps;
@@ -168,8 +164,7 @@ void Map00::special08() {
}
void Map00::special09() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
g_maps->changeMap(0xa11, 1);
@@ -226,31 +221,27 @@ void Map00::special17() {
}
void Map00::special18() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.temple"]
));
}
void Map00::special19() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.jail"]
));
}
void Map00::special20() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.tavern"]
));
}
void Map00::special21() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
2, 0, STRING["maps.map00.sign"],
6, 1, STRING["maps.map00.training"]
));
@@ -264,12 +255,11 @@ void Map00::special22() {
}
void Map00::special23() {
- Sound::sound(SOUND_2);
Common::String msg = STRING["maps.map00.trapdoor"];
if (g_globals->_activeSpells._s.levitate)
msg += STRING["maps.map00.levitate"];
- send(InfoMessage(msg,
+ send(SoundMessage(msg,
[](const Common::KeyState &keyState) {
g_events->focusedView()->close();
if (!g_globals->_activeSpells._s.levitate)
@@ -279,8 +269,7 @@ void Map00::special23() {
}
void Map00::searchStatue() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map00.statue"],
[]() {
Map &map = *g_maps->_currentMap;
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index c386754f3b9..ab106174558 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -86,8 +86,7 @@ void Map01::special03() {
}
void Map01::special04() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map01.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(3, 3);
@@ -120,8 +119,7 @@ void Map01::special08() {
g_events->send("GameParty", GameMessage("UPDATE"));
// Show the message and wait for a keypress
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map01.secret"],
[]() {
Game::Encounter &enc = g_globals->_encounters;
@@ -140,10 +138,7 @@ void Map01::special08() {
}
void Map01::special09() {
- Sound::sound(SOUND_2);
-
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map01.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(8, 0);
@@ -169,8 +164,7 @@ void Map01::special13() {
}
void Map01::special14() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map00.zam0"]
));
}
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 08482f05dd9..850c24bea5f 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -93,8 +93,7 @@ void Map02::special03() {
}
void Map02::special04() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map02.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(7, 7);
@@ -136,13 +135,11 @@ void Map02::special12() {
}
void Map02::special13() {
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map01.zom0"]));
+ send(SoundMessage(0, 1, STRING["maps.map01.zom0"]));
}
void Map02::special14() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map02.pit"],
[]() {
g_maps->_mapPos.x++;
@@ -152,8 +149,7 @@ void Map02::special14() {
}
void Map02::special15() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map02.portal"],
[]() {
int index = g_maps->_mapPos.x - 9;
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 4c2df49dea4..2224f2e3787 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -125,8 +125,7 @@ void Map03::special03() {
}
void Map03::special04() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map01.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(9, 11);
@@ -155,8 +154,7 @@ void Map03::special08() {
}
void Map03::special09() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
g_maps->_mapPos = Common::Point(14, 0);
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 616bb126e07..2ff7749263e 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -46,8 +46,7 @@ void Map04::special() {
}
// Stealable treasure
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map04.treasure"],
[]() {
g_maps->clearSpecial();
@@ -113,8 +112,7 @@ void Map04::special03() {
void Map04::special04() {
if (_data[MAP04_PASSAGE_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map04.passage_outside"],
[]() {
g_maps->_mapPos.x = 13;
@@ -154,8 +152,7 @@ void Map04::special09() {
if (_data[MAP04_STAIRS_OVERRIDE] < 255)
_data[MAP04_STAIRS_OVERRIDE]++;
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
g_maps->_mapPos.x = 0;
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 68203c108e7..12816d72272 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -54,8 +54,7 @@ void Map05::special() {
}
void Map05::special00() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
g_maps->changeMap(0x604, 1);
@@ -94,8 +93,7 @@ void Map05::special05() {
void Map05::special06() {
if (!hasScroll()) {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING[!hasFlag() ? "maps.map05.man1" : "maps.map05.man2"],
[]() {
if (addScroll()) {
@@ -108,8 +106,7 @@ void Map05::special06() {
}
void Map05::special07() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map05.portal"],
[]() {
g_maps->_mapPos.x = 8;
@@ -120,16 +117,14 @@ void Map05::special07() {
}
void Map05::special08() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
2, 1, STRING["maps.sign"],
10, 2, STRING["maps.map05.arena"]
));
}
void Map05::special09() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map05.arena_inside"],
[](const Common::KeyState &keyState) {
if (keyState.keycode == Common::KEYCODE_y) {
@@ -187,8 +182,7 @@ void Map05::encounter(int monsterId) {
}
void Map05::showMessage(const Common::String &msg) {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map05.message1"],
0, 2, msg
));
@@ -215,8 +209,7 @@ bool Map05::addScroll() {
}
}
- Sound::sound(SOUND_2);
- g_events->send(InfoMessage(8, 2, STRING["maps.map05.backpacks_full"]));
+ g_events->send(SoundMessage(8, 2, STRING["maps.map05.backpacks_full"]));
return false;
}
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
index 50c01dc1076..3d4287df474 100644
--- a/engines/mm/mm1/maps/map06.cpp
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -91,8 +91,7 @@ void Map06::special() {
}
void Map06::special00() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map06.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(15, 11);
@@ -102,8 +101,7 @@ void Map06::special00() {
}
void Map06::special01() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map06.portal"],
[]() {
g_maps->_mapPos = Common::Point(7, 0);
@@ -132,8 +130,7 @@ void Map06::special03() {
void Map06::special04() {
if (_data[VAL2]) {
_data[VAL2] = 0;
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map06.acid"]));
+ send(SoundMessage(0, 1, STRING["maps.map06.acid"]));
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
@@ -150,8 +147,7 @@ void Map06::special04() {
}
void Map06::special06() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map06.button"],
[]() {
byte &val1 = (*static_cast<Map06 *>(g_maps->_currentMap))[VAL1];
@@ -162,16 +158,14 @@ void Map06::special06() {
}
void Map06::special07() {
- Sound::sound(SOUND_2);
- send(InfoMessage(17, 1, STRING["maps.poof"]));
+ send(SoundMessage(17, 1, STRING["maps.poof"]));
g_maps->_mapPos.x = 10;
g_maps->_mapPos.y = 11;
g_events->send("Game", GameMessage("UPDATE"));
}
void Map06::special09() {
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map06.banner"]));
+ send(SoundMessage(0, 1, STRING["maps.map06.banner"]));
}
void Map06::special10() {
@@ -199,8 +193,7 @@ void Map06::special13() {
void Map06::special26() {
if (_data[VAL3]) {
- Sound::sound(SOUND_2);
- send(InfoMessage(STRING["maps.map06.wizard"]));
+ send(SoundMessage(STRING["maps.map06.wizard"]));
} else {
g_globals->_treasure[6] = 224;
g_globals->_treasure[7] = 46;
@@ -211,8 +204,7 @@ void Map06::special26() {
}
void Map06::slide() {
- Sound::sound(SOUND_2);
- send(InfoMessage(16, 1, STRING["maps.map06.slide"]));
+ send(SoundMessage(16, 1, STRING["maps.map06.slide"]));
_data[VAL2]++;
g_events->send("Game", GameMessage("UPDATE"));
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 9292687aa14..2cfd9ef6e5f 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -57,8 +57,7 @@ void Map07::special() {
}
void Map07::special00() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
g_maps->_mapPos = Common::Point(0, 15);
@@ -68,8 +67,7 @@ void Map07::special00() {
}
void Map07::special01() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map07.portal"],
[]() {
g_maps->_mapPos = Common::Point(2, 7);
@@ -90,15 +88,13 @@ void Map07::special02() {
}
}
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map07.gate"]));
+ send(SoundMessage(0, 1, STRING["maps.map07.gate"]));
g_maps->_mapPos.y--;
g_events->send("Game", GameMessage("UPDATE"));
}
void Map07::special03() {
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map07.do_not_disturb"]));
+ send(SoundMessage(0, 1, STRING["maps.map07.do_not_disturb"]));
}
void Map07::special04() {
@@ -164,9 +160,8 @@ void Map07::special13() {
c._sex = (c._sex == MALE) ? FEMALE : MALE;
}
- Sound::sound(SOUND_2);
+ g_events->send(SoundMessage(0, 1, STRING["maps.map07.reversal"]));
Sound::sound(SOUND_3);
- g_events->send(InfoMessage(0, 1, STRING["maps.map07.reversal"]));
}
);
}
@@ -184,9 +179,8 @@ void Map07::special15() {
}
}
- Sound::sound(SOUND_2);
+ g_events->send(SoundMessage(0, 1, STRING["maps.map07.might"]));
Sound::sound(SOUND_3);
- g_events->send(InfoMessage(0, 1, STRING["maps.map07.might"]));
}
void Map07::special16() {
@@ -213,8 +207,7 @@ void Map07::setMonsters(int id1, int id2) {
}
void Map07::poolYN(YNCallback callback) {
- Sound::sound(SOUND_2);
- send(InfoMessage(STRING["maps.map07.pool"], callback));
+ send(SoundMessage(STRING["maps.map07.pool"], callback));
}
void Map07::applyCondition(Condition cond) {
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 41f4e1eac82..c74f73da127 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -56,8 +56,7 @@ void Map08::special() {
}
void Map08::special00() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
g_maps->_mapPos = Common::Point(15, 7);
@@ -67,8 +66,7 @@ void Map08::special00() {
}
void Map08::special01() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
g_maps->_mapPos = Common::Point(0, 14);
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index 59e4974bbb2..be307ec4db6 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -54,8 +54,7 @@ void Map09::special() {
}
void Map09::special00() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
g_maps->changeMap(0x802, 1);
@@ -64,8 +63,7 @@ void Map09::special00() {
}
void Map09::special01() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map09.passage_outside"],
[]() {
g_maps->_mapPos = Common::Point(0, 0);
@@ -99,8 +97,7 @@ void Map09::special06() {
}
}
- Sound::sound(SOUND_2);
- g_events->send(InfoMessage(0, 1, STRING["maps.map07.accuracy"]));
+ g_events->send(SoundMessage(0, 1, STRING["maps.map07.accuracy"]));
}
void Map09::special07() {
@@ -112,8 +109,7 @@ void Map09::special07() {
}
}
- Sound::sound(SOUND_2);
- g_events->send(InfoMessage(0, 1, STRING["maps.map07.speed"]));
+ g_events->send(SoundMessage(0, 1, STRING["maps.map07.speed"]));
}
void Map09::special08() {
@@ -123,10 +119,9 @@ void Map09::special08() {
}
const Character &leader = g_globals->_party[0];
- Sound::sound(SOUND_2);
if (leader._alignment == leader._alignmentInitial) {
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map09.shrine1"],
0, 2, STRING["maps.map09.shrine2"]
));
@@ -136,7 +131,7 @@ void Map09::special08() {
g_events->addAction(KEYBIND_SEARCH);
} else {
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map09.shrine1"],
0, 2, STRING["maps.map09.shrine3"]
));
@@ -148,8 +143,7 @@ void Map09::special08() {
}
void Map09::special09() {
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map09.stalactities"]));
+ send(SoundMessage(0, 1, STRING["maps.map09.stalactities"]));
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
@@ -159,10 +153,9 @@ void Map09::special09() {
void Map09::special14() {
g_maps->clearSpecial();
- Sound::sound(SOUND_2);
if (g_globals->_activeSpells._s.levitate) {
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map09.map"],
0, 2, STRING["maps.map09.levitation"]
));
@@ -175,7 +168,7 @@ void Map09::special14() {
c._hpBase /= 2;
}
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map09.map"]
));
}
@@ -183,8 +176,7 @@ void Map09::special14() {
void Map09::special18() {
if (g_globals->_activeSpells._s.psychic_protection) {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
0, 1, STRING["maps.map09.psychic_blast"],
0, 2, STRING["maps.map09.protection"]
));
@@ -211,25 +203,21 @@ void Map09::special18() {
}
void Map09::special25() {
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map09.scrawl"]));
+ send(SoundMessage(0, 1, STRING["maps.map09.scrawl"]));
}
void Map09::special26() {
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map09.corak_was_here"]));
+ send(SoundMessage(0, 1, STRING["maps.map09.corak_was_here"]));
}
void Map09::special27() {
- Sound::sound(SOUND_2);
- send(InfoMessage(0, 1, STRING["maps.map09.message"]));
+ send(SoundMessage(0, 1, STRING["maps.map09.message"]));
}
void Map09::portal(int index) {
_portalIndex = index;
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING["maps.map09.portal"],
[]() {
int index = static_cast<Map09 *>(g_maps->_currentMap)->_portalIndex;
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
index ed474acf147..c6f572e6093 100644
--- a/engines/mm/mm1/maps/map_town.cpp
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -30,8 +30,7 @@ namespace MM1 {
namespace Maps {
void MapTown::blacksmith() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.blacksmith_inside", _mapIndex)],
[]() {
g_events->addView("Blacksmith");
@@ -40,8 +39,7 @@ void MapTown::blacksmith() {
}
void MapTown::inn() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.inn_inside", _mapIndex)],
[]() {
g_events->replaceView("Inn");
@@ -50,8 +48,7 @@ void MapTown::inn() {
}
void MapTown::market() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.market_inside", _mapIndex)],
[]() {
g_events->addView("Market");
@@ -60,8 +57,7 @@ void MapTown::market() {
}
void MapTown::tavern() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.tavern_inside", _mapIndex)],
[]() {
g_events->addView("Tavern");
@@ -70,8 +66,7 @@ void MapTown::tavern() {
}
void MapTown::temple() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.temple_inside", _mapIndex)],
[]() {
g_events->addView("Temple");
@@ -80,8 +75,7 @@ void MapTown::temple() {
}
void MapTown::training() {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.training_inside", _mapIndex)],
[]() {
g_events->addView("Training");
@@ -90,8 +84,7 @@ void MapTown::training() {
}
void MapTown::showSign(const Common::String &msg) {
- Sound::sound(SOUND_2);
- send(InfoMessage(
+ send(SoundMessage(
2, 1, STRING["maps.sign"],
6, 2, msg
));
Commit: 7a8f045e7c40c7057c00cf0abdcf0f6e84ac3bc6
https://github.com/scummvm/scummvm/commit/7a8f045e7c40c7057c00cf0abdcf0f6e84ac3bc6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:21+01:00
Commit Message:
MM: MM1: Support delay timeouts with callbacks in InfoMessage
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/game_messages.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index e3ff8f82a25..52b8440bac9 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -995,7 +995,7 @@ maps:
map10:
levitation: "LEVITATION SAVED YOU."
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
- pit: "JAGGED SLIME PIT! "
+ pit: "JAGGED SLIME PIT!"
poof: "POOF! YOU'VE BEEN TELEPORTED..."
ranalou1: """I'M THE WIZARD RANALOU. ARE YOU HERE TO\nUSE THE PORTALS (Y/N)?"""
ranalou2: """GOOD! INSIDE THIS ROOM ARE 6 PORTALS,\nEACH OF WHICH LEADS TO A CASTLE. THE\nSTATUE OF JUDGEMENT REQUIRES YOU TO FIND\nONE PRISONER FROM EACH OF THESE CASTLES\nBEFORE YOU MAY BE FOUND WORTHY."""
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index 2d86c29ef82..bc21ad02fbb 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -127,7 +127,35 @@ void Map10::special20() {
}
void Map10::special23() {
+ g_maps->clearSpecial();
+ if (g_globals->_activeSpells._s.levitate) {
+ Common::String msg = Common::String::format("%s %s",
+ STRING["maps.map10.pit"].c_str(),
+ STRING["maps.map10.levitation"].c_str());
+ send(SoundMessage(msg));
+ Sound::sound(SOUND_3);
+
+ } else {
+ reduceHP();
+
+ if (getRandomNumber(4) == 4) {
+ Sound::sound(SOUND_2);
+ Sound::sound(SOUND_3);
+ InfoMessage msg(
+ 0, 1, STRING["maps.map10.pit"],
+ []() {
+ g_globals->_encounters.execute();
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
+
+ } else {
+ send(SoundMessage(0, 1, STRING["maps.map10.pit"]));
+ Sound::sound(SOUND_3);
+ }
+ }
}
void Map10::special29() {
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index a2ba2522970..16dd7df46aa 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -100,6 +100,7 @@ struct InfoMessage : public Message {
KeyCallback _keyCallback = nullptr;
bool _largeMessage = false;
bool _sound = false;
+ int _delaySeconds = 0;
InfoMessage();
InfoMessage(const Common::String &str);
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 4992839d64b..1ac3d40154d 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -73,11 +73,15 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
Sound::sound(SOUND_2);
redraw();
+
+ if (msg._delaySeconds)
+ delaySeconds(msg._delaySeconds);
+
return true;
}
bool GameMessages::msgKeypress(const KeypressMessage &msg) {
- if (g_events->focusedView() == this) {
+ if (g_events->focusedView() == this && !isDelayActive()) {
if (_keyCallback) {
_keyCallback(msg);
} else if (msg.keycode == Common::KEYCODE_n) {
@@ -93,6 +97,11 @@ bool GameMessages::msgKeypress(const KeypressMessage &msg) {
return false;
}
+void GameMessages::timeout() {
+ if (_ynCallback)
+ _ynCallback();
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
index 7af5456a863..791b5848be1 100644
--- a/engines/mm/mm1/views/game_messages.h
+++ b/engines/mm/mm1/views/game_messages.h
@@ -41,6 +41,7 @@ public:
void draw() override;
bool msgInfo(const InfoMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
+ void timeout() override;
};
} // namespace Views
Commit: c36fded8a0951162b316a6d30a823d4b9fbd41c7
https://github.com/scummvm/scummvm/commit/c36fded8a0951162b316a6d30a823d4b9fbd41c7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:21+01:00
Commit Message:
MM: MM1: Remainder of map 10
Changed paths:
engines/mm/mm1/maps/map10.cpp
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index bc21ad02fbb..5a029e23cd7 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -159,18 +159,44 @@ void Map10::special23() {
}
void Map10::special29() {
+ send(SoundMessage(STRING["maps.map10.sign1"]));
}
void Map10::special30() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(4) + 3;
+ g_globals->_treasure[5] = 252;
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(9, 9);
+
+ enc._levelIndex = 64;
+ enc._flag = true;
+ enc.execute();
}
void Map10::special31() {
+ send(SoundMessage(STRING["maps.map10.sign2"]));
}
void Map10::special32() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(4) + 3;
+ g_globals->_treasure[5] = 243;
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(8, 12);
+
+ enc._levelIndex = 64;
+ enc._flag = true;
+ enc.execute();
}
void Map10::special33() {
+ g_maps->_mapPos.x = 15;
+ g_events->send("Game", GameMessage("UPDATE"));
}
void Map10::reduceHP() {
Commit: 2de1e45ab51a682b6c6a78d975c28cc6976608e1
https://github.com/scummvm/scummvm/commit/2de1e45ab51a682b6c6a78d975c28cc6976608e1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:21+01:00
Commit Message:
MM: MM1: Added volcano god view for map 11
Changed paths:
A engines/mm/mm1/views/maps/volcano_god.cpp
A engines/mm/mm1/views/maps/volcano_god.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map10.h
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map11.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/access_code.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 52b8440bac9..b9d1be8514e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1002,3 +1002,16 @@ maps:
ranalou3: """THEN BEGONE!"""
sign1: "A SIGN:\n\nEXPERIMENT IN PROGRESS, DO NOT ENTER!"
sign2: "A SIGN:\n\nAUTHORIZED PERSONNEL ONLY! KEEP OUT."
+
+ map11:
+ volcano_god: "THE VOLCANO GOD BELLOWS,\n""WHAT DO YOU SEEK HERE?""\nA) A CHALLENGE B) A RIDDLE C) A CLUE"
+ question: "WHO WAS BRAVE YET FAILED?\n\nANSWER:> .........."
+ sign: "PAINTED IN A BLACK AND WHITE PATTERN,\nA SIGN READS: THE SECOND PART IS THE\nMOST VALUABLE."
+ pit: "PIT OF BUBBLING LAVA!"
+ levitation: "LEVITATION SAVES YOU."
+ virgin: "A LUSCIOUS VIRGIN SHACKLED TO THE WALL!\nA) KISS HER B) RELEASE HER C) LEAVE"
+ tip1: "TRY SETTING 1B,2J"
+ tip2: "THIS CAVERN IS RANDOM UNTIL THE DIALS\nARE SET."
+ dial: "STABILIZATION DIAL # SET (A-Z)?"
+ poof: "POOF! YOU'VE BEEN TELEPORTED..."
+
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 473338d96d3..b9d98b4f675 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -99,6 +99,11 @@ void Map::dataWord(uint16 ofs, uint16 val) {
WRITE_LE_UINT16(&_data[ofs], val);
}
+void Map::reduceHP() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._hpBase /= 2;
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index fec5064c4bd..864de409f16 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -108,6 +108,12 @@ private:
* Load the map's overlay file
*/
void loadOverlay();
+protected:
+ /**
+ * Divides all the party's Hp in half
+ */
+ void reduceHP();
+
public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index c74f73da127..3251009a9fc 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -95,8 +95,7 @@ void Map08::special05() {
void Map08::special06() {
if (_data[VAL1]) {
- for (uint i = 0; i < g_globals->_party.size(); ++i)
- g_globals->_party[i]._hpBase /= 2;
+ reduceHP();
send(InfoMessage(18, 2, STRING["maps.map08.zap"]));
Sound::sound(SOUND_3);
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index be307ec4db6..4c4f6dd54a6 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -144,11 +144,7 @@ void Map09::special08() {
void Map09::special09() {
send(SoundMessage(0, 1, STRING["maps.map09.stalactities"]));
-
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- c._hpBase /= 2;
- }
+ reduceHP();
}
void Map09::special14() {
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index 5a029e23cd7..ed9535550b7 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -199,13 +199,6 @@ void Map10::special33() {
g_events->send("Game", GameMessage("UPDATE"));
}
-void Map10::reduceHP() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- g_globals->_currCharacter = &g_globals->_party[i];
- g_globals->_currCharacter->_hpBase /= 2;
- }
-}
-
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map10.h b/engines/mm/mm1/maps/map10.h
index 52114c8185e..5d3a554624e 100644
--- a/engines/mm/mm1/maps/map10.h
+++ b/engines/mm/mm1/maps/map10.h
@@ -44,7 +44,6 @@ private:
void special31();
void special32();
void special33();
- void reduceHP();
const SpecialFn SPECIAL_FN[34] = {
&Map10::special00,
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 9c63ea690e5..816cc237175 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -29,14 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 641
+#define VAL2 642
+#define VAL3 643
+
void Map11::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 14; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[65 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +47,79 @@ void Map11::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ g_globals->_treasure[5] = 0;
+
+ if (getRandomNumber(50) == 10) {
+ pit();
+
+ } else {
+ if (_data[VAL1] == 66 && _data[VAL2] == 74) {
+ g_maps->_mapPos = Common::Point(7, 11);
+ } else {
+ g_maps->_mapPos.x = getRandomNumber(15);
+ g_maps->_mapPos.y = getRandomNumber(15);
+ }
+
+ send(SoundMessage(STRING["maps.map11.poof"]));
+ g_events->send("Game", GameMessage("UPDATE"));
+ }
}
void Map11::special00() {
+ send(SoundMessage(
+ STRING["maps.ladder_up"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 2);
+ g_maps->changeMap(0xf04, 2);
+ }
+ ));
+}
+
+void Map11::special01() {
+ if (_data[VAL1]) {
+ g_maps->_mapPos = Common::Point(8, 5);
+ g_maps->changeMap(0x604, 1);
+ } else {
+ g_events->addView("VolcanoGod");
+ }
+}
+
+void Map11::special02() {
+}
+
+void Map11::special03() {
+}
+
+void Map11::special04() {
+}
+
+void Map11::special05() {
+}
+
+void Map11::special06() {
+}
+
+void Map11::special07() {
+}
+
+void Map11::special08() {
+}
+
+void Map11::pit() {
+ if (g_globals->_activeSpells._s.levitate) {
+ Common::String msg = Common::String::format("%s %s",
+ STRING["maps.map10.pit"].c_str(),
+ STRING["maps.map10.levitation"].c_str());
+ send(SoundMessage(msg));
+ Sound::sound(SOUND_3);
+
+ } else {
+ reduceHP();
+ reduceHP();
+ send(SoundMessage(STRING["maps.map10.pit"]));
+ Sound::sound(SOUND_3);
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map11.h b/engines/mm/mm1/maps/map11.h
index 7c19632c9e5..3ac1ab253d9 100644
--- a/engines/mm/mm1/maps/map11.h
+++ b/engines/mm/mm1/maps/map11.h
@@ -32,9 +32,31 @@ class Map11 : public Map {
typedef void (Map11:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void pit();
- const SpecialFn SPECIAL_FN[1] = {
- &Map11::special00
+ const SpecialFn SPECIAL_FN[14] = {
+ &Map11::special00,
+ &Map11::special01,
+ &Map11::special02,
+ &Map11::special03,
+ &Map11::special04,
+ &Map11::special05,
+ &Map11::special06,
+ &Map11::special07,
+ &Map11::special08,
+ &Map11::special08,
+ &Map11::special08,
+ &Map11::special02,
+ &Map11::special02,
+ &Map11::special02
};
public:
Map11() : Map(11, "cave7", 0x212) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 800143d2ea5..6393478375d 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -45,6 +45,7 @@
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/resistances.h"
+#include "mm/mm1/views/maps/volcano_god.h"
#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/views/spells/detect_magic.h"
#include "mm/mm1/views/spells/duplication.h"
@@ -82,6 +83,7 @@ private:
Views::Maps::Arrested _arrested;
Views::Maps::Resistances _resistances;
+ Views::Maps::VolcanoGod _volcanoGod;
Views::Spells::CastSpell _castSpell;
Views::Spells::DetectMagic _detectMagicSpell;
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
index 4d1594e9f9b..858fcb42853 100644
--- a/engines/mm/mm1/views/maps/access_code.cpp
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -64,8 +64,13 @@ bool AccessCode::msgKeypress(const KeypressMessage &msg) {
(msg.keycode >= Common::KEYCODE_0 &&
msg.keycode <= Common::KEYCODE_z)) {
_code += toupper(msg.ascii);
+ redraw();
+
if (_code.size() == MAX_CODE_LENGTH)
codeEntered();
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE && !_code.empty()) {
+ _code.deleteLastChar();
+ redraw();
}
}
@@ -118,7 +123,7 @@ void AccessCode::incorrectCode() {
delaySeconds(2);
}
-} // namespace Spells
+} // namespace Maps
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
new file mode 100644
index 00000000000..7109ce7e71a
--- /dev/null
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -0,0 +1,149 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/volcano_god.h"
+#include "mm/mm1/maps/map11.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define MAX_ANSWER_LENGTH 8
+#define ANSWER_OFFSET 636
+#define VAL1 641
+
+VolcanoGod::VolcanoGod() : TextView("VolcanoGod") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool VolcanoGod::msgFocus(const FocusMessage &msg) {
+ _answer = "";
+ _mode = CHOOSE_OPTION;
+ Sound::sound(SOUND_2);
+ return TextView::msgFocus(msg);
+}
+
+void VolcanoGod::draw() {
+ clearSurface();
+
+ switch (_mode) {
+ case CHOOSE_OPTION:
+ writeString(0, 1, STRING["maps.map11.volcano_god"]);
+ break;
+
+ case ENTER_RESPONSE:
+ writeString(0, 1, STRING["maps.map11.question"]);
+ writeString(9, 3, _answer);
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool VolcanoGod::msgKeypress(const KeypressMessage &msg) {
+ if (!isDelayActive()) {
+ switch (_mode) {
+ case CHOOSE_OPTION:
+ switch (msg.keycode) {
+ case Common::KEYCODE_a:
+ challenge();
+ break;
+ case Common::KEYCODE_b:
+ riddle();
+ break;
+ case Common::KEYCODE_c:
+ clue();
+ break;
+ default:
+ break;
+ }
+
+ case ENTER_RESPONSE:
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ responseEntered();
+ } else if (msg.keycode == Common::KEYCODE_SPACE ||
+ (msg.keycode >= Common::KEYCODE_0 &&
+ msg.keycode <= Common::KEYCODE_z)) {
+ _answer += toupper(msg.ascii);
+ redraw();
+
+ if (_answer.size() == MAX_ANSWER_LENGTH)
+ responseEntered();
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE && !_answer.empty()) {
+ _answer.deleteLastChar();
+ redraw();
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+void VolcanoGod::challenge() {
+ Game::Encounter &enc = g_globals->_encounters;
+ close();
+
+ enc.clearMonsters();
+ enc.addMonster(10, 12);
+ for (int i = 1; i < 10; ++i)
+ enc.addMonster(7, 8);
+
+ enc._levelIndex = 96;
+ enc._flag = true;
+ enc.execute();
+}
+
+void VolcanoGod::riddle() {
+ Sound::sound(SOUND_2);
+ _mode = ENTER_RESPONSE;
+ redraw();
+}
+
+void VolcanoGod::clue() {
+ close();
+ g_maps->_mapPos = Common::Point(0, 5);
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void VolcanoGod::responseEntered() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Common::String properAnswer;
+ for (int i = 0; i < 8 && map[MAX_ANSWER_LENGTH + i]; ++i)
+ properAnswer += map[ANSWER_OFFSET + i] + 30;
+
+ if (_answer == properAnswer) {
+ (*g_maps->_currentMap)[VAL1]++;
+ g_events->addAction(KEYBIND_SEARCH);
+ } else {
+ g_maps->_mapPos = Common::Point(7, 2);
+ g_maps->changeMap(0xf04, 2);
+ }
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/volcano_god.h b/engines/mm/mm1/views/maps/volcano_god.h
new file mode 100644
index 00000000000..114b3652e45
--- /dev/null
+++ b/engines/mm/mm1/views/maps/volcano_god.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_VOLCANO_GOD_H
+#define MM1_VIEWS_MAPS_VOLCANO_GOD_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class VolcanoGod : public TextView {
+private:
+ enum Mode { CHOOSE_OPTION, ENTER_RESPONSE };
+ Mode _mode = CHOOSE_OPTION;
+ Common::String _answer;
+
+ void challenge();
+ void riddle();
+ void clue();
+ void responseEntered();
+public:
+ VolcanoGod();
+ virtual ~VolcanoGod() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 588e3ebc5ab..c7029ef1151 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -53,6 +53,7 @@ MODULE_OBJS := \
mm1/views/maps/access_code.o \
mm1/views/maps/arrested.o \
mm1/views/maps/resistances.o \
+ mm1/views/maps/volcano_god.o \
mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
mm1/views/spells/detect_magic.o \
Commit: c6662cfdcd574a12789668c74b8708cf29e16db2
https://github.com/scummvm/scummvm/commit/c6662cfdcd574a12789668c74b8708cf29e16db2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:21+01:00
Commit Message:
MM: MM1: Finished map 11
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map11.h
engines/mm/mm1/views/maps/volcano_god.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b9d1be8514e..1b039663430 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1012,6 +1012,6 @@ maps:
virgin: "A LUSCIOUS VIRGIN SHACKLED TO THE WALL!\nA) KISS HER B) RELEASE HER C) LEAVE"
tip1: "TRY SETTING 1B,2J"
tip2: "THIS CAVERN IS RANDOM UNTIL THE DIALS\nARE SET."
- dial: "STABILIZATION DIAL # SET (A-Z)?"
+ dial: "STABILIZATION DIAL #%c SET (A-Z)?"
poof: "POOF! YOU'VE BEEN TELEPORTED..."
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 816cc237175..33a25e1e3a1 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -86,24 +86,51 @@ void Map11::special01() {
}
void Map11::special02() {
+ g_maps->clearSpecial();
+ pit();
}
void Map11::special03() {
+ send(SoundMessage(STRING["maps.map11.sign"]));
}
void Map11::special04() {
+ send(SoundMessage(STRING["maps.map11.virgin"],
+ [](const Common::KeyState &ks) {
+ switch (ks.keycode) {
+ case Common::KEYCODE_a:
+ g_events->close();
+ g_events->send(SoundMessage(STRING["maps.map11.tip1"]));
+ break;
+ case Common::KEYCODE_b:
+ static_cast<MM1::Maps::Map11 *>(g_maps->_currentMap)->challenge();
+ break;
+ case Common::KEYCODE_c:
+ case Common::KEYCODE_ESCAPE:
+ g_events->close();
+ break;
+ default:
+ break;
+ }
+ }
+ ));
}
void Map11::special05() {
+ send(SoundMessage(STRING["maps.map11.tip2"]));
}
void Map11::special06() {
+ selectDial(0);
}
void Map11::special07() {
+ selectDial(1);
}
void Map11::special08() {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
}
void Map11::pit() {
@@ -122,6 +149,41 @@ void Map11::pit() {
}
}
+void Map11::selectDial(int dialIndex) {
+ _dialIndex = dialIndex;
+ Common::String msg = Common::String::format(
+ STRING["maps.map11.dial"].c_str(), '1' + dialIndex);
+
+ send(SoundMessage(msg,
+ [](const Common::KeyState &ks) {
+ if (ks.keycode >= Common::KEYCODE_a &&
+ ks.keycode <= Common::KEYCODE_z) {
+ g_events->close();
+ static_cast<Map11 *>(g_maps->_currentMap)->setDialChar(ks.ascii);
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ }
+ ));
+}
+
+void Map11::challenge() {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_events->close();
+
+ enc.clearMonsters();
+ enc.addMonster(10, 12);
+ for (int i = 1; i < 10; ++i)
+ enc.addMonster(7, 8);
+
+ enc._levelIndex = 96;
+ enc._flag = true;
+ enc.execute();
+}
+
+void Map11::setDialChar(char c) {
+ _data[VAL2 + _dialIndex] = c;
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map11.h b/engines/mm/mm1/maps/map11.h
index 3ac1ab253d9..37144a2c144 100644
--- a/engines/mm/mm1/maps/map11.h
+++ b/engines/mm/mm1/maps/map11.h
@@ -31,6 +31,8 @@ namespace Maps {
class Map11 : public Map {
typedef void (Map11:: *SpecialFn)();
private:
+ int _dialIndex = 0;
+
void special00();
void special01();
void special02();
@@ -41,6 +43,7 @@ private:
void special07();
void special08();
void pit();
+ void selectDial(int dialIndex);
const SpecialFn SPECIAL_FN[14] = {
&Map11::special00,
@@ -65,6 +68,16 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Creates a challenge encounter
+ */
+ void challenge();
+
+ /**
+ * Set the alphabetic character for the current dial
+ */
+ void setDialChar(char c);
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
index 7109ce7e71a..ee6aa748483 100644
--- a/engines/mm/mm1/views/maps/volcano_god.cpp
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -103,17 +103,7 @@ bool VolcanoGod::msgKeypress(const KeypressMessage &msg) {
}
void VolcanoGod::challenge() {
- Game::Encounter &enc = g_globals->_encounters;
- close();
-
- enc.clearMonsters();
- enc.addMonster(10, 12);
- for (int i = 1; i < 10; ++i)
- enc.addMonster(7, 8);
-
- enc._levelIndex = 96;
- enc._flag = true;
- enc.execute();
+ static_cast<MM1::Maps::Map11 *>(g_maps->_currentMap)->challenge();
}
void VolcanoGod::riddle() {
Commit: 210d48f921c3c4d04ac36a76c1fdfc004932dbb0
https://github.com/scummvm/scummvm/commit/210d48f921c3c4d04ac36a76c1fdfc004932dbb0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:21+01:00
Commit Message:
MM: MM1: Added map 12
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map12.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 1b039663430..fcc21426e9e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1015,3 +1015,12 @@ maps:
dial: "STABILIZATION DIAL #%c SET (A-Z)?"
poof: "POOF! YOU'VE BEEN TELEPORTED..."
+ map12:
+ polyhedron1: "ATOP A CRYSTAL PYRAMID SPINS A GLOWING\nPOLYHEDRON. STOP IT ON SIDE (1-9)?"
+ polyhedron2: "THE POLYHEDRON IS SET ON %c\nSPIN IT (Y/N)?"
+ polyhedron3: "A GLOWING POLYHEDRON IS SET ON SIDE %c%c"
+ lever: "PLATINUM LEVER PROTRUDES FROM THE WALL."
+ wont_budge: "IT WON'T BUDGE!"
+ pull_it: "PULL IT (Y/N)?"
+ incorrect: "INCORRECT SETTINGS!"
+ correct: "YOU HAVE MASTERED THE MAGIC SQUARE!\n+2 INT, +20 GEMS, +200 GOLD, +2000 EXP"
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index 50fc9b4b126..e51a285d934 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -29,13 +29,16 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define CORRECT 464
+#define SELECTIONS 473
+
void Map12::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[69 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +47,174 @@ void Map12::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map12::special00() {
+ send(SoundMessage(
+ STRING["maps.ladder_up"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 13);
+ g_maps->changeMap(0x105, 2);
+ }
+ ));
+}
+
+void Map12::special01() {
+ Common::String line1 = STRING["maps.map12.lever"];
+ Common::String line2;
+
+ for (int i = 0; i < 9; ++i) {
+ if (!_data[SELECTIONS + i]) {
+ line2 = STRING["maps.map12.wont_budge"];
+ break;
+ }
+ }
+
+ if (!line2.empty()) {
+ send(SoundMessage(0, 1, line1, 0, 2, line2));
+ } else {
+ line2 = STRING["maps.map12.pull_it"];
+ send(SoundMessage(
+ 0, 1, line1,
+ 0, 2, line2,
+ []() {
+ Map12 &map = *static_cast<Map12 *>(g_maps->_currentMap);
+ int i;
+ for (i = 0; i < 9; ++i) {
+ if (map[SELECTIONS + i] != map[CORRECT + i])
+ break;
+ }
+
+ if (i < 9) {
+ g_events->send(SoundMessage(STRING["maps.map12.incorrect"]));
+
+ } else {
+ // Reward the party
+ for (i = 0; i < (int)g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c._intelligence._base < 25) {
+ c._intelligence._current = c._intelligence._base += 2;
+ }
+
+ c._gems = MIN((int)c._gems + 20, 0xffff);
+ c._gold += 200;
+ c._exp += 2000;
+ }
+
+ g_events->send(SoundMessage(STRING["maps.map12.correct"]));
+ }
+ }
+ ));
+ }
+}
+
+void Map12::special02() {
+ polyhedron('1', (unsigned char)182);
+}
+
+void Map12::special03() {
+ polyhedron('1', (unsigned char)179);
+}
+
+void Map12::special04() {
+ polyhedron('1', (unsigned char)176);
+}
+
+void Map12::special05() {
+ polyhedron('1', '1');
+}
+
+void Map12::special06() {
+ polyhedron('1', (unsigned char)178);
+}
+
+void Map12::special07() {
+ polyhedron('1', (unsigned char)181);
+}
+
+void Map12::special08() {
+ polyhedron('1', (unsigned char)180);
+}
+
+void Map12::special09() {
+ setPolyhedron(0);
+}
+
+void Map12::special10() {
+ setPolyhedron(1);
+}
+
+void Map12::special11() {
+ setPolyhedron(2);
+}
+
+void Map12::special12() {
+ setPolyhedron(3);
+}
+
+void Map12::special13() {
+ setPolyhedron(4);
+}
+
+void Map12::special14() {
+ setPolyhedron(5);
+}
+
+void Map12::special15() {
+ setPolyhedron(6);
+}
+
+void Map12::special16() {
+ setPolyhedron(7);
+}
+
+void Map12::special17() {
+ setPolyhedron(8);
+}
+
+void Map12::polyhedron(unsigned char side1, unsigned char side2) {
+ Common::String msg = Common::String::format(
+ STRING["maps.map12.polyhedron3"].c_str(), side1, side2);
+ send(SoundMessage(msg));
+}
+
+void Map12::setPolyhedron(int polyIndex) {
+ _polyIndex = polyIndex;
+
+ if (_data[SELECTIONS + polyIndex]) {
+ Common::String msg = Common::String::format(
+ STRING["maps.map12.polyhedron2"].c_str(),
+ _data[SELECTIONS + polyIndex]);
+ send(SoundMessage(
+ msg,
+ []() {
+ static_cast<Map12 *>(g_maps->_currentMap)->spinPolyhedron(0);
+ g_events->send("Game", GameMessage("UPDATE"));
+ }
+ ));
+
+ } else {
+ send(SoundMessage(
+ STRING["maps.map12.polyhedron1"],
+ [](const Common::KeyState &ks) {
+ if (ks.keycode >= Common::KEYCODE_0 &&
+ ks.keycode <= Common::KEYCODE_9) {
+ g_events->close();
+ static_cast<Map12 *>(g_maps->_currentMap)->spinPolyhedron(
+ ks.ascii | 0x80);
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ }
+ ));
+ }
+}
+
+void Map12::spinPolyhedron(byte newSide) {
+ _data[SELECTIONS + _polyIndex] = newSide;
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map12.h b/engines/mm/mm1/maps/map12.h
index 00ac3ae775c..f9306820321 100644
--- a/engines/mm/mm1/maps/map12.h
+++ b/engines/mm/mm1/maps/map12.h
@@ -31,10 +31,48 @@ namespace Maps {
class Map12 : public Map {
typedef void (Map12:: *SpecialFn)();
private:
+ int _polyIndex = 0;
+
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special17();
+ void polyhedron(unsigned char side1, unsigned char side2);
+ void setPolyhedron(int polyIndex);
- const SpecialFn SPECIAL_FN[1] = {
- &Map12::special00
+ const SpecialFn SPECIAL_FN[18] = {
+ &Map12::special00,
+ &Map12::special01,
+ &Map12::special02,
+ &Map12::special03,
+ &Map12::special04,
+ &Map12::special05,
+ &Map12::special06,
+ &Map12::special07,
+ &Map12::special08,
+ &Map12::special09,
+ &Map12::special10,
+ &Map12::special11,
+ &Map12::special12,
+ &Map12::special13,
+ &Map12::special14,
+ &Map12::special15,
+ &Map12::special16,
+ &Map12::special17
};
public:
Map12() : Map(12, "cave8", 0x601) {}
@@ -43,6 +81,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Spins a polyhedron
+ */
+ void spinPolyhedron(byte newSide);
};
} // namespace Maps
Commit: 307223f54a737d8854621950da0a918f470ef9c0
https://github.com/scummvm/scummvm/commit/307223f54a737d8854621950da0a918f470ef9c0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:21+01:00
Commit Message:
MM: MM1: Added map 13
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map13.cpp
engines/mm/mm1/maps/map13.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index fcc21426e9e..ace184d6603 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1024,3 +1024,11 @@ maps:
pull_it: "PULL IT (Y/N)?"
incorrect: "INCORRECT SETTINGS!"
correct: "YOU HAVE MASTERED THE MAGIC SQUARE!\n+2 INT, +20 GEMS, +200 GOLD, +2000 EXP"
+
+ map13:
+ passage_outside: "A PASSAGE LEADS OUTDOORS, EXIT (Y/N)?"
+ snake_pit: "SNAKE PIT! "
+ spike_pit: "A TRAP! A PIT FULL OF POISONOUS SPIKES\nOPENS BELOW THE PARTY!\n"
+ levitation1: "LUCKILY,YOUR LEVITATION SPELL SAVED YOU!"
+ levitation2: "LEVITATION SAVED YOU."
+ remains: "SMASHED REMAINS OF STONE STATUES\nSEEM SUSPICIOUSLY LIFELIKE."
diff --git a/engines/mm/mm1/maps/map13.cpp b/engines/mm/mm1/maps/map13.cpp
index 8b6f091233a..d251c31c963 100644
--- a/engines/mm/mm1/maps/map13.cpp
+++ b/engines/mm/mm1/maps/map13.cpp
@@ -29,14 +29,19 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 143
+#define MONSTER_ID1 389
+#define MONSTER_ID2 445
+
void Map13::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 23; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[74 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +49,130 @@ void Map13::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
+
g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+ int index;
+ if (g_maps->_mapPos.y < 5) {
+ index = 0;
+ } else if (g_maps->_mapPos.y < 9) {
+ index = 14;
+ } else if (g_maps->_mapPos.x < 9) {
+ index = 28;
+ } else {
+ index = 42;
+ }
+
+ int monsterCount = getRandomNumber(7) + 5;
+ enc.clearMonsters();
+
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(_data[MONSTER_ID1 + index + i],
+ _data[MONSTER_ID2 + index + i]);
+
+ enc._flag = true;
+ enc._levelIndex = 48;
+ enc.execute();
}
void Map13::special00() {
+ _data[VAL1] = 0;
+ send(SoundMessage(
+ STRING["maps.map13.passage_outside"],
+ []() {
+ g_maps->_mapPos = Common::Point(8, 4);
+ g_maps->changeMap(0x703, 2);
+ }
+ ));
+}
+
+void Map13::special01() {
+ if (_data[VAL1]) {
+ g_maps->clearSpecial();
+ g_globals->_treasure[5] = 246;
+ g_events->addAction(KEYBIND_SEARCH);
+ } else {
+ _data[VAL1]++;
+ encounter(getRandomNumber(6) + 3, 9, 6);
+ }
+}
+
+void Map13::special02() {
+ g_maps->clearSpecial();
+
+ if (g_globals->_activeSpells._s.levitate) {
+ send(SoundMessage(
+ 0, 1, STRING["maps.map13.spike_pit"],
+ 0, 2, STRING["maps.map13.levitation1"]
+ ));
+ } else if (!g_globals->_activeSpells._s.poison) {
+ reduceHP();
+ reduceHP();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._condition & BAD_CONDITION))
+ c._condition = POISONED;
+ }
+
+ send(SoundMessage(STRING["maps.map13.pit"]));
+ }
+}
+
+void Map13::special06() {
+ send(SoundMessage(STRING["maps.map13.remains"]));
+}
+
+void Map13::special10() {
+ g_maps->clearSpecial();
+ Sound::sound(SOUND_2);
+ Sound::sound(SOUND_3);
+
+ if (g_globals->_activeSpells._s.levitate) {
+ send(InfoMessage(
+ 0, 1, STRING["maps.map13.snake_pit"],
+ 0, 2, STRING["maps.map13.levitation2"]
+ ));
+ Sound::sound(SOUND_3);
+
+ } else if (!g_globals->_activeSpells._s.poison) {
+ reduceHP();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._condition & BAD_CONDITION))
+ c._condition = POISONED;
+ }
+
+ InfoMessage msg(
+ 0, 1, STRING["maps.map13.snake_pit"],
+ []() {
+ static_cast<Map13 *>(g_maps->_currentMap)->encounter(
+ getRandomNumber(3) + 10, 14, 1);
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
+ }
+}
+
+void Map13::special18() {
+ encounter(getRandomNumber(4) + 2, 2, 5);
+}
+
+void Map13::special22() {
+ encounter(getRandomNumber(3) + 3, 9, 6);
+}
+
+void Map13::encounter(size_t count, byte id1, byte id2) {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ enc.clearMonsters();
+ for (size_t i = 0; i < count; ++i)
+ enc.addMonster(id1, id2);
+
+ enc._flag = true;
+ enc._levelIndex = 64;
+ enc.execute();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map13.h b/engines/mm/mm1/maps/map13.h
index 99839bf7bdd..676115bdc0b 100644
--- a/engines/mm/mm1/maps/map13.h
+++ b/engines/mm/mm1/maps/map13.h
@@ -32,9 +32,37 @@ class Map13 : public Map {
typedef void (Map13:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special06();
+ void special10();
+ void special18();
+ void special22();
- const SpecialFn SPECIAL_FN[1] = {
- &Map13::special00
+ const SpecialFn SPECIAL_FN[23] = {
+ &Map13::special00,
+ &Map13::special01,
+ &Map13::special02,
+ &Map13::special02,
+ &Map13::special02,
+ &Map13::special02,
+ &Map13::special06,
+ &Map13::special06,
+ &Map13::special06,
+ &Map13::special06,
+ &Map13::special10,
+ &Map13::special10,
+ &Map13::special10,
+ &Map13::special10,
+ &Map13::special10,
+ &Map13::special10,
+ &Map13::special10,
+ &Map13::special10,
+ &Map13::special18,
+ &Map13::special18,
+ &Map13::special18,
+ &Map13::special18,
+ &Map13::special22
};
public:
Map13() : Map(13, "cave9", 0xA00) {}
@@ -43,6 +71,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Start an encounter
+ */
+ void encounter(size_t count, byte id1, byte id2);
};
} // namespace Maps
Commit: 24196fc777790b48db423b45c7546f5020dedda4
https://github.com/scummvm/scummvm/commit/24196fc777790b48db423b45c7546f5020dedda4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:22+01:00
Commit Message:
MM: MM1: Added map 14
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map14.cpp
engines/mm/mm1/maps/map14.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ace184d6603..52d4d1d93be 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1032,3 +1032,10 @@ maps:
levitation1: "LUCKILY,YOUR LEVITATION SPELL SAVED YOU!"
levitation2: "LEVITATION SAVED YOU."
remains: "SMASHED REMAINS OF STONE STATUES\nSEEM SUSPICIOUSLY LIFELIKE."
+
+ map14:
+ words: "CARVED ON A BLOCK OF ICE ARE THE WORDS:\nSTART AT 15-7 AND WALK TO DOOM!"
+ passage: "A SECRET PASSAGE TO DOOM, TAKE IT (Y/N)?"
+ pool: "THE POOL OF HEALTH GRANTS THOSE WHO ARE\nWORTHY +4 ENDURANCE!"
+ surrounded: "YOU'VE BEEN SURROUNDED BY THE DARK RIDERAND HIS MEN! HE CHALLENGES YOU TO A DUEL...ACCEPT (Y/N)?"
+ castle: "THE FABELED CASTLE DOOM!\nWILL YOU ENTER (Y/N)?"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 38cda7b694b..5724bed9467 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -75,12 +75,19 @@ enum CharFlags1 {
CHARFLAG1_1 = 1
};
+enum CharFlags2 {
+ CHARFLAG2_1 = 1,
+ CHARFLAG2_2 = 2,
+ CHARFLAG2_4 = 4,
+ CHARFLAG2_8 = 8
+};
+
enum CharFlags5 {
CHARFLAG5_8 = 8
};
enum CharFlags11 {
- CHARFLAG11_1 = 1,
+ CHARFLAG11_GOT_ENDURANCE = 1,
CHARFLAG11_2 = 2,
CHARFLAG11_4 = 4,
CHARFLAG11_GOT_MIGHT = 8,
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
index 518edd7f3ae..f7b228981f4 100644
--- a/engines/mm/mm1/maps/map14.cpp
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -29,14 +29,19 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 75
+#define VAL2 148
+#define VAL3 395
+
void Map14::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 6; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[57 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +49,128 @@ void Map14::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
+
g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+ int monsterCount = getRandomNumber(3);
+ int id1 = getRandomNumber(16);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, 7);
+
+ enc._levelIndex = 5;
+ enc._flag = true;
+ enc.execute();
}
void Map14::special00() {
+ if (_data[VAL1]) {
+ g_maps->clearSpecial();
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._flags[2] |= CHARFLAG2_8;
+ g_events->addAction(KEYBIND_SEARCH);
+
+ } else {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (g_globals->_party[i]._flags[2] & CHARFLAG2_8) {
+ g_maps->clearSpecial();
+ g_events->addAction(KEYBIND_SEARCH);
+ return;
+ }
+ }
+
+ send(SoundMessage(STRING["maps.map14.surrounded"],
+ [](const Common::KeyState &ks) {
+ Map14 &map = *static_cast<Map14 *>(g_maps->_currentMap);
+ Game::Encounter &enc = g_globals->_encounters;
+
+ if (ks.keycode == Common::KEYCODE_y ||
+ ks.keycode == Common::KEYCODE_n) {
+ g_events->close();
+
+ // TODO: The original seems to be backwards
+ if (ks.keycode == Common::KEYCODE_n &&
+ getRandomNumber(3) == 3) {
+ g_maps->_mapPos = Common::Point(15, 10);
+ } else {
+ map[VAL1]++;
+ enc.clearMonsters();
+ enc.addMonster(2, 12);
+ for (int i = 1; i < 12; ++i)
+ enc.addMonster(13, 8);
+
+ enc._levelIndex = 80;
+ enc._flag = true;
+ enc.execute();
+ }
+ }
+ }
+ ));
+ }
+}
+
+void Map14::special01() {
+ _data[VAL1] = 0;
+ _data[VAL2]++;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map14::special02() {
+ if (_data[VAL3] & 0x80) {
+ g_maps->_mapPos = Common::Point(7, 0);
+ g_maps->changeMap(0x706, 3);
+ } else if (_data[VAL3]) {
+ _data[VAL3] = 0;
+ } else {
+ g_events->findView("View")->redraw();
+
+ send(SoundMessage(
+ STRING["maps.map14.castle"],
+ [](const Common::KeyState &ks) {
+ Map14 &map = *static_cast<Map14 *>(g_maps->_currentMap);
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+ map[VAL3]++;
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->close();
+ map[VAL3] = 0xff;
+ }
+ }
+ ));
+ }
+}
+
+void Map14::special03() {
+ send(SoundMessage(STRING["maps.map14.words"]));
+}
+
+void Map14::special04() {
+ if (_data[VAL2]) {
+ send(SoundMessage(
+ STRING["maps.map14.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(4, 4);
+ g_maps->changeMap(0x706, 3);
+ }
+ ));
+ } else {
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+}
+
+void Map14::special05() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._flags[11] & CHARFLAG11_GOT_ENDURANCE)) {
+ c._flags[11] |= CHARFLAG11_GOT_ENDURANCE;
+ int endurance = c._endurance._base + 4;
+ if (endurance < 30) {
+ c._endurance._base = c._endurance._current = endurance;
+ }
+ }
+ }
+
+ send(SoundMessage(STRING["maps.map14.pool"]));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map14.h b/engines/mm/mm1/maps/map14.h
index f26f3d5a40a..47528713e64 100644
--- a/engines/mm/mm1/maps/map14.h
+++ b/engines/mm/mm1/maps/map14.h
@@ -32,9 +32,19 @@ class Map14 : public Map {
typedef void (Map14:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map14::special00
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+
+ const SpecialFn SPECIAL_FN[6] = {
+ &Map14::special00,
+ &Map14::special01,
+ &Map14::special02,
+ &Map14::special03,
+ &Map14::special04,
+ &Map14::special05
};
public:
Map14() : Map(14, "areaa1", 0xF01) {}
Commit: 62754ae60264e3908256995e6b65c94486ce08af
https://github.com/scummvm/scummvm/commit/62754ae60264e3908256995e6b65c94486ce08af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:22+01:00
Commit Message:
MM: MM1: Added map 15
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map15.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 52d4d1d93be..1d5a6361052 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1039,3 +1039,11 @@ maps:
pool: "THE POOL OF HEALTH GRANTS THOSE WHO ARE\nWORTHY +4 ENDURANCE!"
surrounded: "YOU'VE BEEN SURROUNDED BY THE DARK RIDERAND HIS MEN! HE CHALLENGES YOU TO A DUEL...ACCEPT (Y/N)?"
castle: "THE FABELED CASTLE DOOM!\nWILL YOU ENTER (Y/N)?"
+
+ map15:
+ lava: "LAVA FILLS THE VALLEY OF FIRE!"
+ body: "THE DRAGONS BODY DISAPPEARS, EXCEPT\nFOR A SHINY TOOTH!"
+ cove: "A PIRATES SECRET COVE, SEARCH (Y/N)?"
+ percella1: "I AM PERCELLA THE DRUID AND I HAVE WHAT\nYOU NEED. BUT PROMISE ME THAT YOU WON'T\nHELP THAT DEMONIC MENACE. ACCEPT (Y/N)?"
+ percella2: "THEN MEET MY PETS!"
+ its_hot: "IT'S HOT!"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 0e0946951c7..828d24ac98d 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -89,6 +89,24 @@ struct ItemsArray : public Common::Array<Item>, public TextParser {
Item *getItem(byte index) const;
};
+class Treasure {
+private:
+ byte _data[TREASURE_COUNT];
+public:
+ Treasure() {
+ clear();
+ }
+
+ byte &operator[](uint i) {
+ assert(i < TREASURE_COUNT);
+ return _data[i];
+ }
+
+ void clear() {
+ Common::fill(&_data[0], &_data[TREASURE_COUNT], 0);
+ }
+};
+
inline bool isWeapon(byte id) {
return id >= 1 && id <= 60;
};
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 613aae92a66..0d24ea944d6 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -180,8 +180,7 @@ void ViewBase::forward(KeybindingAction action) {
}
}
- Common::fill(&g_globals->_treasure[0],
- &g_globals->_treasure[TREASURE_COUNT], 0);
+ g_globals->_treasure.clear();
int maxVal = map[Maps::MAP_29];
if (g_engine->getRandomNumber(maxVal) == maxVal)
@@ -209,8 +208,7 @@ void ViewBase::backwards() {
}
}
- Common::fill(&g_globals->_treasure[0],
- &g_globals->_treasure[TREASURE_COUNT], 0);
+ g_globals->_treasure.clear();
int maxVal = map[Maps::MAP_29];
if (g_engine->getRandomNumber(maxVal) == maxVal)
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 1fa4ac4c75e..8de5a229f02 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -51,7 +51,7 @@ public:
bool _heardRumor = false;
Game::Encounter _encounters;
Monsters _monsters;
- byte _treasure[TREASURE_COUNT];
+ Treasure _treasure;
byte _delay = 5;
int _nonCombatEffectCtr = 0, _combatEffectCtr = 0;
bool _inCombat = false;
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 12816d72272..f64b234e3c7 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -138,7 +138,7 @@ void Map05::special09() {
(*g_maps->_currentMap)[MAP_47] = 1;
(*g_maps->_currentMap)[MAP_33] = 4;
(*g_maps->_currentMap)[MAP_MAX_MONSTERS] = 10;
- Common::fill(&g_globals->_treasure[0], &g_globals->_treasure[TREASURE_COUNT], 0);
+ g_globals->_treasure.clear();
// TODO: Space key - is it used in-game?
g_events->addKeypress(Common::KEYCODE_SPACE);
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index d09f881fb33..5931c857509 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -29,14 +29,20 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 350
+#define VAL2 118
+#define VAL3 361
+#define VAL4 362
+
void Map15::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 9; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[60 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +50,157 @@ void Map15::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (g_maps->_mapPos.y >= 3) {
+ g_globals->_treasure.clear();
+
+ if (getRandomNumber(20) == 20) {
+ if (_data[VAL1] > 14)
+ _data[VAL1] = 14;
+
+ g_globals->_activeSpells._s.fire = 0;
+ enc.clearMonsters();
+ for (uint i = 0; i < _data[VAL1]; ++i)
+ enc.addMonster(7, 8);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+
+ } else {
+ send(SoundMessage(16, 1, STRING["maps.map15.its_hot"]));
+
+ if (!g_globals->_activeSpells._s.fire) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._hpBase = MAX((int)c._hpBase - 15, 0);
+ }
+ }
+ }
+ } else if (getRandomNumber(100) != 100) {
+ g_events->addAction(KEYBIND_SEARCH);
+ } else {
+ Character &c = g_globals->_party[0];
+ g_globals->_currCharacter = &c;
+ int id1 = getRandomNumber(2 + ((c._level < 12) ? c._level : 14));
+ int monsterCount = getRandomNumber((id1 < 15) ? 13 : 4);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, 11);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
}
void Map15::special00() {
+ send(SoundMessage(STRING["maps.map15.lava"]));
+}
+
+void Map15::special01() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ if (_data[VAL2]) {
+ send(SoundMessage(STRING["maps.map15.dragon"]));
+ g_globals->_treasure[5] = 244;
+ g_events->addAction(KEYBIND_SEARCH);
+
+ } else {
+ _data[VAL2]++;
+
+ enc.clearMonsters();
+ enc.addMonster(15, 9);
+ enc._levelIndex = 5;
+ enc._flag = true;
+ enc.execute();
+ }
+}
+
+void Map15::special02() {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+ _data[VAL2]++;
+
+ int monsterCount = getRandomNumber(4) + 1;
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(15, 9);
+
+ enc._levelIndex = 48;
+ enc._flag = true;
+ enc.execute();
+}
+
+void Map15::special03() {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+ _data[VAL2]++;
+
+ enc.clearMonsters();
+ for (int i = 0; i < 10; ++i)
+ enc.addMonster(15, 9);
+
+ enc._levelIndex = 48;
+ enc._flag = true;
+}
+
+void Map15::special04() {
+ _data[VAL3] = 250;
+ _data[VAL4] = 100;
+ cove();
+}
+
+void Map15::special05() {
+ _data[VAL3] = 251;
+ _data[VAL4] = 200;
+ cove();
+}
+
+void Map15::special06() {
+ g_maps->clearSpecial();
+ send(SoundMessage(STRING["maps.map15.percella1"],
+ [](const Common::KeyState &ks) {
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+ g_globals->_treasure[5] = 233;
+ g_events->addAction(KEYBIND_SEARCH);
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->send(SoundMessage(STRING["maps.map15.percella1"]));
+ g_maps->_mapPos = Common::Point(14, 2);
+ g_events->send("Game", GameMessage("UPDATE"));
+ }
+ }
+ ));
+}
+
+void Map15::special08() {
+ _data[VAL2] = 0;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map15::cove() {
+ send(SoundMessage(STRING["maps.map15.cove"],
+ []() {
+ Map15 &map = *static_cast<Map15 *>(g_maps->_currentMap);
+ g_maps->clearSpecial();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ int idx = c._backpack.indexOf(map[VAL3]);
+ if (idx != -1) {
+ c._backpack.removeAt(idx);
+ g_globals->_treasure[8] = map[VAL4];
+ g_globals->_treasure[7] = 7;
+ g_globals->_treasure[6] = 208;
+ break;
+ }
+ }
+
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map15.h b/engines/mm/mm1/maps/map15.h
index 415729387b4..228f5a4d788 100644
--- a/engines/mm/mm1/maps/map15.h
+++ b/engines/mm/mm1/maps/map15.h
@@ -32,9 +32,25 @@ class Map15 : public Map {
typedef void (Map15:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special08();
+ void cove();
- const SpecialFn SPECIAL_FN[1] = {
- &Map15::special00
+ const SpecialFn SPECIAL_FN[9] = {
+ &Map15::special00,
+ &Map15::special01,
+ &Map15::special02,
+ &Map15::special03,
+ &Map15::special04,
+ &Map15::special05,
+ &Map15::special06,
+ &Map15::special00,
+ &Map15::special08
};
public:
Map15() : Map(15, "areaa2", 0x502) {}
Commit: df97eb2a3919c6d36337bb2c68059a0f411b90aa
https://github.com/scummvm/scummvm/commit/df97eb2a3919c6d36337bb2c68059a0f411b90aa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:22+01:00
Commit Message:
MM: MM1: Added map 16
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map16.cpp
engines/mm/mm1/maps/map16.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 1d5a6361052..7cfd581b66b 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1047,3 +1047,11 @@ maps:
percella1: "I AM PERCELLA THE DRUID AND I HAVE WHAT\nYOU NEED. BUT PROMISE ME THAT YOU WON'T\nHELP THAT DEMONIC MENACE. ACCEPT (Y/N)?"
percella2: "THEN MEET MY PETS!"
its_hot: "IT'S HOT!"
+
+ map16:
+ loser: "LOSER!\n"
+ gems: "GEMS!\n"
+ gold: "GOLD!\n"
+ exp: "EXP!\n"
+ water: "THE WATER ERUPTS VIOLENTLY,\nREVEALING A TREMENDOUS SERPENT"
+ wheel: "EMBEDDED IN THE SIDE OF THE MOUNTAIN IS\nA LARGE WHEEL COVERED IN STRANGE AND\nARCHAIC SYMBOLS. SPIN THE WHEEL (Y/N)?"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 5724bed9467..e05c3453673 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -79,7 +79,11 @@ enum CharFlags2 {
CHARFLAG2_1 = 1,
CHARFLAG2_2 = 2,
CHARFLAG2_4 = 4,
- CHARFLAG2_8 = 8
+ CHARFLAG2_8 = 8,
+ CHARFLAG2_10 = 0x10,
+ CHARFLAG2_20 = 0x20,
+ CHARFLAG2_40 = 0x40,
+ CHARFLAG2_80 = 0x80
};
enum CharFlags5 {
diff --git a/engines/mm/mm1/maps/map16.cpp b/engines/mm/mm1/maps/map16.cpp
index ea28cd1a6a7..605ba85d47f 100644
--- a/engines/mm/mm1/maps/map16.cpp
+++ b/engines/mm/mm1/maps/map16.cpp
@@ -29,14 +29,20 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 83
+#define VAL2 84
+#define VAL3 85
+#define VAL4 87
+
void Map16::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 8; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[59 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +50,152 @@ void Map16::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
+
+ if (getRandomNumber(100) == 100) {
+ Character &c = g_globals->_party[0];
+ g_globals->_currCharacter = &c;
+ int id1 = getRandomNumber(c._level >= 12 ? 14 : c._level) + 2;
+ int monsterCount = getRandomNumber(id1 < 15 ? 13 : 4);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, 11);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+
+ } else {
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+}
+
+void Map16::special00() {
+ if (_data[VAL1]) {
+ g_maps->clearSpecial();
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ c._flags[2] |= CHARFLAG2_1;
+ }
+
+ g_events->addAction(KEYBIND_SEARCH);
+
+ } else {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ if (c._flags[2] & CHARFLAG2_1) {
+ g_maps->clearSpecial();
+ g_events->addAction(KEYBIND_SEARCH);
+ return;
+ }
+ }
+
+ _data[VAL1]++;
+ send(SoundMessage(STRING["maps.map16.water"],
+ [](const Common::KeyState &ks) {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ enc.clearMonsters();
+ enc.addMonster(4, 12);
+ for (int i = 1; i < 12; ++i)
+ enc.addMonster(12, 11);
+
+ enc._levelIndex = 80;
+ enc._flag = true;
+ enc.execute();
+ }
+ ));
+ }
+}
+
+void Map16::special01() {
+ send(SoundMessage(STRING["maps.map16.wheel"],
+ []() {
+ // Original called sound 1 20 times. This seems excessive
+ Sound::sound(SOUND_1);
+
+ static_cast<Map16 *>(g_maps->_currentMap)->wheelSpin();
+ }
+ ));
+}
+
+void Map16::special02() {
+ _data[VAL1] = 0;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map16::special03() {
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
-void Map16::special00() {
+void Map16::wheelSpin() {
+ Common::String line;
+ int val;
+ SoundMessage msg;
+ msg._largeMessage = true;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ _data[VAL2] = i;
+
+ // Count set flags
+ _data[VAL4] = 0;
+ byte v = c._flags[2];
+ for (int j = 0; j < 4; ++j, v >>= 1) {
+ if (v & 1)
+ _data[VAL4]++;
+ }
+
+ line = c._name;
+ while (line.size() < 17)
+ line += ' ';
+
+ if (_data[VAL4] == 0) {
+ line += STRING["maps.map16.loser"];
+ } else {
+ c._flags[2] |= CHARFLAG2_80;
+
+ switch (getRandomNumber(6)) {
+ case 1:
+ val = 2000 << _data[VAL4];
+ WRITE_LE_UINT16(&_data[VAL3], val);
+ c._exp += val;
+ line += Common::String::format("+%d %s", val,
+ STRING["maps.map16.exp"].c_str());
+ break;
+
+ case 2:
+ val = 500 << _data[VAL4];
+ WRITE_LE_UINT16(&_data[VAL3], val);
+ c._gold += val;
+ line += Common::String::format("+%d %s", val,
+ STRING["maps.map16.gold"].c_str());
+ break;
+
+ case 3:
+ val = 15 << _data[VAL4];
+ WRITE_LE_UINT16(&_data[VAL3], val);
+ c._gems += val;
+ line += Common::String::format("+%d %s", val,
+ STRING["maps.map16.gems"].c_str());
+ break;
+
+ default:
+ line += STRING["maps.map16.loser"];
+ break;
+ }
+ }
+
+ msg._lines.push_back(Line(0, i, line));
+ }
+
+ // Display the results
+ send(msg);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map16.h b/engines/mm/mm1/maps/map16.h
index aa7985ee717..c0230428983 100644
--- a/engines/mm/mm1/maps/map16.h
+++ b/engines/mm/mm1/maps/map16.h
@@ -32,9 +32,19 @@ class Map16 : public Map {
typedef void (Map16:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
- const SpecialFn SPECIAL_FN[1] = {
- &Map16::special00
+ const SpecialFn SPECIAL_FN[8] = {
+ &Map16::special00,
+ &Map16::special01,
+ &Map16::special02,
+ &Map16::special03,
+ &Map16::special03,
+ &Map16::special03,
+ &Map16::special03,
+ &Map16::special03
};
public:
Map16() : Map(16, "areaa3", 0xB02) {}
@@ -43,6 +53,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Spins the wheel and grants each party member a result
+ */
+ void wheelSpin();
};
} // namespace Maps
Commit: cc7f5628093d8f8fe3aafe3daaeb5885772f3b7f
https://github.com/scummvm/scummvm/commit/cc7f5628093d8f8fe3aafe3daaeb5885772f3b7f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:22+01:00
Commit Message:
MM: MM1: Most of map 17
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map17.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 7cfd581b66b..b76f688c74f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1055,3 +1055,12 @@ maps:
exp: "EXP!\n"
water: "THE WATER ERUPTS VIOLENTLY,\nREVEALING A TREMENDOUS SERPENT"
wheel: "EMBEDDED IN THE SIDE OF THE MOUNTAIN IS\nA LARGE WHEEL COVERED IN STRANGE AND\nARCHAIC SYMBOLS. SPIN THE WHEEL (Y/N)?"
+
+ map17:
+ options: "1) RED THORAC 2) BLUE OGRAM\n3) GREEN BAGAR 4) YELLOW LIMRA\n5) PURPLE SAGRAN 6) ORANGE OOLAK\n7) BLACK DRESIDION 8) WHITE DILITHIUM"
+ bridge: "A WOODEN BRIDGE EXTENDES ACROSS THE',0Dh,'OCEAN INTO THE MIST. A HOODED FIGURE\nMATERIALIZES, ""TO CROSS YOU MUST EACH\nANSWER A QUESTION, ACCEPT (Y/N)?"""
+ color: "WHAT IS YOUR COLOR(1-8)?"
+ wrong: "WRONG!"
+ correct: "CORRECT!"
+ islands: "ATOP THIS PEAK 5 ISLANDS CAN BE SEEN\nTO THE SOUTHEAST"
+ wave: "A TIDAL WAVE SWEEPS THE PARTY AWAY!"
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index a89fe80bea6..0fd1293346d 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -29,14 +29,19 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 509
+#define VAL2 510
+#define VAL3 511
+
void Map17::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 9; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[60 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +49,50 @@ void Map17::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (getRandomNumber(100) == 100) {
+ Character &c = g_globals->_party[0];
+ g_globals->_currCharacter = &c;
+ int id1 = getRandomNumber(c._level >= 12 ? 14 : c._level) + 2;
+ int monsterCount = getRandomNumber(id1 < 15 ? 13 : 4);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, 11);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+
+ } else if (getRandomNumber(30) == 10) {
+ g_maps->_mapPos = Common::Point(15, 15);
+ send(SoundMessage(STRING["maps.map17.wave"]));
+ g_events->send("Game", GameMessage("UPDATE"));
+
+ } else {
+ g_events->addAction(KEYBIND_SEARCH);
+ }
}
void Map17::special00() {
+ send(SoundMessage("maps.map17.islands"));
+}
+
+void Map17::special01() {
+}
+
+void Map17::special02() {
+ if (_data[VAL3]) {
+ g_globals->_treasure[5] = 236;
+ g_events->addAction(KEYBIND_SEARCH);
+ } else {
+ g_events->addKeypress((Common::KeyCode)211);
+ }
+}
+
+void Map17::special03() {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map17.h b/engines/mm/mm1/maps/map17.h
index 2493f1a5e8b..d873b07c548 100644
--- a/engines/mm/mm1/maps/map17.h
+++ b/engines/mm/mm1/maps/map17.h
@@ -32,9 +32,20 @@ class Map17 : public Map {
typedef void (Map17:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map17::special00
+ void special01();
+ void special02();
+ void special03();
+
+ const SpecialFn SPECIAL_FN[9] = {
+ &Map17::special00,
+ &Map17::special01,
+ &Map17::special02,
+ &Map17::special03,
+ &Map17::special03,
+ &Map17::special03,
+ &Map17::special03,
+ &Map17::special03,
+ &Map17::special03
};
public:
Map17() : Map(17, "areaa4", 0x103) {}
Commit: 97bc7d57dcae6985603743db5d1ac05c0963043a
https://github.com/scummvm/scummvm/commit/97bc7d57dcae6985603743db5d1ac05c0963043a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:22+01:00
Commit Message:
MM: MM1: Fix incorrect addAction calls
Changed paths:
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map14.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map16.cpp
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 2224f2e3787..ba9396037c1 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -114,6 +114,8 @@ void Map03::special01() {
0, 1, STRING["maps.map03.telgoran4"]
));
}
+
+ g_events->addKeypress((Common::KeyCode)160);
}
void Map03::special02() {
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 2ff7749263e..8cc3757fdf9 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -183,8 +183,7 @@ void Map04::special13() {
g_maps->clearSpecial();
g_events->addView("Arrested");
} else {
- // TODO: Sends key 160 to game_keypress, which doesn't seem to handle it
- //g_events->addAction();
+ g_events->addKeypress((Common::KeyCode)160);
}
}
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 2cfd9ef6e5f..46ae3e26e6e 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -82,9 +82,11 @@ void Map07::special02() {
for (uint j = 0; j < c._equipped.size(); ++j) {
if (c._equipped[j]._id >= BRONZE_KEY_ID &&
- c._equipped[j]._id <= DIAMOND_KEY_ID)
+ c._equipped[j]._id <= DIAMOND_KEY_ID) {
// Someone has a key
+ g_events->addKeypress((Common::KeyCode)160);
return;
+ }
}
}
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 33a25e1e3a1..567fc15bac5 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -160,7 +160,7 @@ void Map11::selectDial(int dialIndex) {
ks.keycode <= Common::KEYCODE_z) {
g_events->close();
static_cast<Map11 *>(g_maps->_currentMap)->setDialChar(ks.ascii);
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
}
}
));
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index e51a285d934..ec4d02c0775 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -206,7 +206,7 @@ void Map12::setPolyhedron(int polyIndex) {
g_events->close();
static_cast<Map12 *>(g_maps->_currentMap)->spinPolyhedron(
ks.ascii | 0x80);
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
}
}
));
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
index f7b228981f4..6009ea3a878 100644
--- a/engines/mm/mm1/maps/map14.cpp
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -68,13 +68,13 @@ void Map14::special00() {
g_maps->clearSpecial();
for (uint i = 0; i < g_globals->_party.size(); ++i)
g_globals->_party[i]._flags[2] |= CHARFLAG2_8;
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
} else {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
if (g_globals->_party[i]._flags[2] & CHARFLAG2_8) {
g_maps->clearSpecial();
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
return;
}
}
@@ -112,7 +112,7 @@ void Map14::special00() {
void Map14::special01() {
_data[VAL1] = 0;
_data[VAL2]++;
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
}
void Map14::special02() {
@@ -154,7 +154,7 @@ void Map14::special04() {
}
));
} else {
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
}
}
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index 5931c857509..4b87050f23b 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -78,7 +78,8 @@ void Map15::special() {
}
}
} else if (getRandomNumber(100) != 100) {
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
+
} else {
Character &c = g_globals->_party[0];
g_globals->_currCharacter = &c;
@@ -177,7 +178,7 @@ void Map15::special06() {
void Map15::special08() {
_data[VAL2] = 0;
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
}
void Map15::cove() {
diff --git a/engines/mm/mm1/maps/map16.cpp b/engines/mm/mm1/maps/map16.cpp
index 605ba85d47f..82943b6574c 100644
--- a/engines/mm/mm1/maps/map16.cpp
+++ b/engines/mm/mm1/maps/map16.cpp
@@ -66,7 +66,7 @@ void Map16::special() {
enc.execute();
} else {
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
}
}
@@ -79,7 +79,7 @@ void Map16::special00() {
c._flags[2] |= CHARFLAG2_1;
}
- g_events->addAction(KEYBIND_SEARCH);
+ g_events->addKeypress((Common::KeyCode)160);
} else {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Commit: 805aad54898abe2c199c3f7c9efe8cc3912d7b53
https://github.com/scummvm/scummvm/commit/805aad54898abe2c199c3f7c9efe8cc3912d7b53
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:22+01:00
Commit Message:
MM: MM1: Remainder of map 17
Changed paths:
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map17.h
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index e05c3453673..89ddfa62b57 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -86,6 +86,11 @@ enum CharFlags2 {
CHARFLAG2_80 = 0x80
};
+enum CharFlags4 {
+ CHARFLAG4_COLOR = 0xf,
+ CHARFLAG4_80 = 0x80
+};
+
enum CharFlags5 {
CHARFLAG5_8 = 8
};
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 0fd1293346d..76082b6b4b4 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -79,6 +79,11 @@ void Map17::special00() {
}
void Map17::special01() {
+ send(SoundMessage(STRING["maps.map17.bridge"],
+ []() {
+ static_cast<Map17 *>(g_maps->_currentMap)->askQuestion();
+ }
+ ));
}
void Map17::special02() {
@@ -95,6 +100,64 @@ void Map17::special03() {
g_globals->_encounters.execute();
}
+void Map17::askQuestion(uint partyIndex) {
+ if (partyIndex >= g_globals->_party.size()) {
+ if (_data[VAL3]) {
+ g_maps->_mapPos.y = 2;
+ g_events->send("Game", GameMessage("UPDATE"));
+ } else {
+ g_events->addKeypress((Common::KeyCode)160);
+ }
+ return;
+ }
+
+ _data[VAL1] = partyIndex;
+ Character &c = g_globals->_party[partyIndex];
+ g_globals->_currCharacter = &c;
+
+ if (!(c._condition & BAD_CONDITION)) {
+ InfoMessage msg(
+ 0, 0, STRING["maps.map17.color"],
+ 0, 2, STRING["maps.map17.options"],
+ [](const Common::KeyState &ks) {
+ Map17 &map = *static_cast<Map17 *>(g_maps->_currentMap);
+ if (ks.keycode >= Common::KEYCODE_1 &&
+ ks.keycode <= Common::KEYCODE_9) {
+ map[VAL2] = ks.ascii - '1';
+
+ Common::String msg;
+ Character &c = *g_globals->_currCharacter;
+ int val = c._flags[2] & 0xf;
+ if (!val || (val & 7) != map[VAL2]) {
+ c._condition = ERADICATED;
+ msg = STRING["maps.map17.wrong"];
+ } else {
+ map[VAL3]++;
+ c._flags[4] |= CHARFLAG4_80;
+ msg = STRING["maps.map17.correct"];
+ }
+
+ Sound::sound(SOUND_3);
+ InfoMessage msg2;
+ msg2._largeMessage = true;
+ msg2._delaySeconds = 1;
+ msg2._lines.push_back(Line(0, 0, STRING["maps.map17.color"]));
+ msg2._lines.push_back(Line(0, 2, STRING["maps.map17.options"]));
+ msg2._lines.push_back(Line(16, 5, msg));
+ msg2._ynCallback = []() {
+ Map17 &map = *static_cast<Map17 *>(g_maps->_currentMap);
+ map.askQuestion(map[VAL1] + 1);
+ };
+
+ g_events->send(msg2);
+ }
+ }
+ );
+ msg._largeMessage = true;
+ send(msg);
+ }
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map17.h b/engines/mm/mm1/maps/map17.h
index d873b07c548..79bbcf5ebc3 100644
--- a/engines/mm/mm1/maps/map17.h
+++ b/engines/mm/mm1/maps/map17.h
@@ -54,6 +54,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Ask a given party member a question
+ */
+ void askQuestion(uint partyIndex = 0);
};
} // namespace Maps
Commit: 8692b23b56db41de8e1328fa90e416041af7a636
https://github.com/scummvm/scummvm/commit/8692b23b56db41de8e1328fa90e416041af7a636
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:22+01:00
Commit Message:
MM: MM1: Most of map 18
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map14.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map16.cpp
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map18.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b76f688c74f..4daa16b9d73 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1064,3 +1064,15 @@ maps:
correct: "CORRECT!"
islands: "ATOP THIS PEAK 5 ISLANDS CAN BE SEEN\nTO THE SOUTHEAST"
wave: "A TIDAL WAVE SWEEPS THE PARTY AWAY!"
+
+ map18:
+ passage: "CAVERNOUS PASSAGE TO ERLIQUIN,\nTAKE IT (Y/N)?"
+ cave: "A CAVE, ENTER (Y/N)?"
+ castle_north: "CASTLE BLACKRIDGE NORTH, ENTER (Y/N)?"
+ castle_south: "CASTLE BLACKRIDGE SOUTH, ENTER (Y/N)?"
+ ruins: "ANCIENT RUINS OF A DESERTED WIZARDS LAIR\nSHOW SIGNS OF RECENT USE, ENTER (Y/N)?"
+ gates: "THE GATES TO ANOTHER WORLD!\n"
+ congratulations: "CONGRATULATIONS DISTINGUISHED \nTRAVELERS! THE GATES ARE NOW\nOPEN TO YOU, IN ORDER TO PASS\nTHROUGH YOU MUST FIRST FIND\nMIGHT AND MAGIC BOOK TWO !!!"
+ sign1: "A SIGN POINTING S. READS: BLACKRIDGE N."
+ sign2: "A SIGN POINTING E. READS: BLACKRIDGE S."
+ sign3: "A SIGN POINTING E. READS: ERLIQUIN"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 89ddfa62b57..ca0f9641d82 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -104,6 +104,10 @@ enum CharFlags11 {
CHARFLAG11_GOT_SPEED = 0x20
};
+enum CharFlags14 {
+ CHARFLAG14_80 = 0x80
+};
+
class Inventory {
public:
struct Entry {
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 864de409f16..30db2e829b1 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -114,6 +114,14 @@ protected:
*/
void reduceHP();
+ /**
+ * Many special methods return a 160 key, but it
+ * doesn't look like the game uses. My current
+ * assumption is that this is just a convenient
+ * 'do nothing' return value
+ */
+ static void none160() {}
+
public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index ba9396037c1..9097d9d7a62 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -115,7 +115,7 @@ void Map03::special01() {
));
}
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
void Map03::special02() {
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 8cc3757fdf9..23c8d45c98b 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -183,7 +183,7 @@ void Map04::special13() {
g_maps->clearSpecial();
g_events->addView("Arrested");
} else {
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
}
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 46ae3e26e6e..4636207251c 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -84,7 +84,7 @@ void Map07::special02() {
if (c._equipped[j]._id >= BRONZE_KEY_ID &&
c._equipped[j]._id <= DIAMOND_KEY_ID) {
// Someone has a key
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
return;
}
}
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 567fc15bac5..2d44c8514ed 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -160,7 +160,7 @@ void Map11::selectDial(int dialIndex) {
ks.keycode <= Common::KEYCODE_z) {
g_events->close();
static_cast<Map11 *>(g_maps->_currentMap)->setDialChar(ks.ascii);
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
}
));
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index ec4d02c0775..5fcb5a400ff 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -206,7 +206,7 @@ void Map12::setPolyhedron(int polyIndex) {
g_events->close();
static_cast<Map12 *>(g_maps->_currentMap)->spinPolyhedron(
ks.ascii | 0x80);
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
}
));
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
index 6009ea3a878..5974fcf55d4 100644
--- a/engines/mm/mm1/maps/map14.cpp
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -68,13 +68,13 @@ void Map14::special00() {
g_maps->clearSpecial();
for (uint i = 0; i < g_globals->_party.size(); ++i)
g_globals->_party[i]._flags[2] |= CHARFLAG2_8;
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
} else {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
if (g_globals->_party[i]._flags[2] & CHARFLAG2_8) {
g_maps->clearSpecial();
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
return;
}
}
@@ -112,7 +112,7 @@ void Map14::special00() {
void Map14::special01() {
_data[VAL1] = 0;
_data[VAL2]++;
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
void Map14::special02() {
@@ -154,7 +154,7 @@ void Map14::special04() {
}
));
} else {
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
}
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index 4b87050f23b..c53bfb9b02e 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -78,7 +78,7 @@ void Map15::special() {
}
}
} else if (getRandomNumber(100) != 100) {
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
} else {
Character &c = g_globals->_party[0];
@@ -178,7 +178,7 @@ void Map15::special06() {
void Map15::special08() {
_data[VAL2] = 0;
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
void Map15::cove() {
diff --git a/engines/mm/mm1/maps/map16.cpp b/engines/mm/mm1/maps/map16.cpp
index 82943b6574c..4affe5f80f5 100644
--- a/engines/mm/mm1/maps/map16.cpp
+++ b/engines/mm/mm1/maps/map16.cpp
@@ -66,7 +66,7 @@ void Map16::special() {
enc.execute();
} else {
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
}
@@ -79,7 +79,7 @@ void Map16::special00() {
c._flags[2] |= CHARFLAG2_1;
}
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
} else {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 76082b6b4b4..41860ef8fd5 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -106,7 +106,7 @@ void Map17::askQuestion(uint partyIndex) {
g_maps->_mapPos.y = 2;
g_events->send("Game", GameMessage("UPDATE"));
} else {
- g_events->addKeypress((Common::KeyCode)160);
+ none160();
}
return;
}
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index 8b091990976..56845596721 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -29,14 +29,16 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 235
+#define VAL2 196
+
void Map18::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 10; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[61 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +46,134 @@ void Map18::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map18::special00() {
+ send(SoundMessage(
+ STRING["maps.map18.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(0, 7);
+ g_maps->changeMap(0xb1a, 1);
+ }
+ ));
+}
+
+void Map18::special01() {
+ if (_data[VAL1] & 0x80) {
+ g_maps->_mapPos = Common::Point(0, 7);
+ g_maps->changeMap(0x508, 3);
+
+ } else if (_data[VAL1] == 0) {
+ _data[VAL1] = 0;
+
+ } else {
+ g_events->findView("Game")->redraw();
+ send(SoundMessage(
+ STRING["maps.map18.blackridge_south"],
+ [](const Common::KeyState &ks) {
+ Map18 &map = *static_cast<Map18 *>(g_maps->_currentMap);
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+ map[VAL1] = 0xff;
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->close();
+ map[VAL1]++;
+ }
+ }
+ ));
+ }
+}
+
+void Map18::special02() {
+ if (_data[VAL2] & 0x80) {
+ g_maps->_mapPos = Common::Point(7, 15);
+ g_maps->changeMap(0xf08, 3);
+
+ } else if (_data[VAL1] == 0) {
+ _data[VAL2] = 0;
+
+ } else {
+ g_events->findView("Game")->redraw();
+ send(SoundMessage(
+ STRING["maps.map18.blackridge_north"],
+ [](const Common::KeyState &ks) {
+ Map18 &map = *static_cast<Map18 *>(g_maps->_currentMap);
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+ map[VAL2] = 0xff;
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->close();
+ map[VAL2]++;
+ }
+ }
+ ));
+ }
+}
+
+void Map18::special03() {
+ send(SoundMessage(STRING["maps.map18.ruins"],
+ []() {
+ Map18 &map = *static_cast<Map18 *>(g_maps->_currentMap);
+ g_maps->_mapPos = Common::Point(2, 2);
+ g_maps->changeMap(0xf03, 3);
+ }
+ ));
+}
+
+void Map18::special04() {
+ send(SoundMessage(STRING["maps.map18.sign1"]));
+}
+
+void Map18::special05() {
+ send(SoundMessage(STRING["maps.map18.sign2"]));
+}
+
+void Map18::special06() {
+ send(SoundMessage(STRING["maps.map18.sign3"]));
+}
+
+void Map18::special07() {
+ send(SoundMessage(STRING["maps.map18.gates"]));
+
+ bool hasWonGame = false;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ if (c._flags[14] & CHARFLAG14_80)
+ hasWonGame = true;
+ }
+
+ if (hasWonGame)
+ wonGame();
+}
+
+void Map18::special08() {
+ send(SoundMessage(
+ STRING["maps.map18.cave"],
+ []() {
+ g_maps->_mapPos = Common::Point(15, 7);
+ g_maps->changeMap(0x202, 1);
+ }
+ ));
+}
+
+void Map18::special09() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[5] = 238;
+ g_globals->_treasure[1] = 4;
+ g_globals->_treasure[2] = 4;
+ g_globals->_treasure[6] = 96;
+ g_globals->_treasure[7] = 9;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map18::wonGame() {
+ // TODO: display win message
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map18.h b/engines/mm/mm1/maps/map18.h
index ce0c551fb94..904e32f1476 100644
--- a/engines/mm/mm1/maps/map18.h
+++ b/engines/mm/mm1/maps/map18.h
@@ -32,9 +32,28 @@ class Map18 : public Map {
typedef void (Map18:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void wonGame();
- const SpecialFn SPECIAL_FN[1] = {
- &Map18::special00
+ const SpecialFn SPECIAL_FN[10] = {
+ &Map18::special00,
+ &Map18::special01,
+ &Map18::special02,
+ &Map18::special03,
+ &Map18::special04,
+ &Map18::special05,
+ &Map18::special06,
+ &Map18::special07,
+ &Map18::special08,
+ &Map18::special09
};
public:
Map18() : Map(18, "areab1", 0xA00) {}
Commit: 6dfe1611ae196f2a432f8f2ea4cf9650ff5d5aee
https://github.com/scummvm/scummvm/commit/6dfe1611ae196f2a432f8f2ea4cf9650ff5d5aee
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:23+01:00
Commit Message:
MM: MM1: Added Won Game view, finishing map 18
Changed paths:
A engines/mm/mm1/views/maps/won_game.cpp
A engines/mm/mm1/views/maps/won_game.h
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map18.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index 56845596721..991be3f4aa1 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -149,7 +149,7 @@ void Map18::special07() {
}
if (hasWonGame)
- wonGame();
+ g_events->addView("WonGame");
}
void Map18::special08() {
@@ -172,10 +172,6 @@ void Map18::special09() {
g_events->addAction(KEYBIND_SEARCH);
}
-void Map18::wonGame() {
- // TODO: display win message
-}
-
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map18.h b/engines/mm/mm1/maps/map18.h
index 904e32f1476..d8ef1609ed5 100644
--- a/engines/mm/mm1/maps/map18.h
+++ b/engines/mm/mm1/maps/map18.h
@@ -41,7 +41,6 @@ private:
void special07();
void special08();
void special09();
- void wonGame();
const SpecialFn SPECIAL_FN[10] = {
&Map18::special00,
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 6393478375d..52391a546b6 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -46,6 +46,7 @@
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/volcano_god.h"
+#include "mm/mm1/views/maps/won_game.h"
#include "mm/mm1/views/spells/cast_spell.h"
#include "mm/mm1/views/spells/detect_magic.h"
#include "mm/mm1/views/spells/duplication.h"
@@ -84,7 +85,7 @@ private:
Views::Maps::Arrested _arrested;
Views::Maps::Resistances _resistances;
Views::Maps::VolcanoGod _volcanoGod;
-
+ Views::Maps::WonGame _wonGame;
Views::Spells::CastSpell _castSpell;
Views::Spells::DetectMagic _detectMagicSpell;
Views::Spells::Duplication _duplicationSpell;
diff --git a/engines/mm/mm1/views/maps/won_game.cpp b/engines/mm/mm1/views/maps/won_game.cpp
new file mode 100644
index 00000000000..4f0951c79bf
--- /dev/null
+++ b/engines/mm/mm1/views/maps/won_game.cpp
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/won_game.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+WonGame::WonGame() : TextView("WonGame") {
+ Common::Rect r = getLineBounds(5, 11);
+ r.right = 30 * 8;
+ _bounds = r;
+}
+
+void WonGame::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map18.congratulations"]);
+ Sound::sound(SOUND_3);
+}
+
+bool WonGame::msgKeypress(const KeypressMessage &msg) {
+ close();
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/won_game.h b/engines/mm/mm1/views/maps/won_game.h
new file mode 100644
index 00000000000..acea9889520
--- /dev/null
+++ b/engines/mm/mm1/views/maps/won_game.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_WON_GAME_H
+#define MM1_VIEWS_MAPS_WON_GAME_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class WonGame : public TextView {
+public:
+ WonGame();
+ virtual ~WonGame() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c7029ef1151..8e026531a13 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -54,6 +54,7 @@ MODULE_OBJS := \
mm1/views/maps/arrested.o \
mm1/views/maps/resistances.o \
mm1/views/maps/volcano_god.o \
+ mm1/views/maps/won_game.o \
mm1/views/spells/spell_view.o \
mm1/views/spells/cast_spell.o \
mm1/views/spells/detect_magic.o \
Commit: 5b37a16c4c7a8cc59cff424e09f39321cc8cdb72
https://github.com/scummvm/scummvm/commit/5b37a16c4c7a8cc59cff424e09f39321cc8cdb72
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:23+01:00
Commit Message:
MM: MM1: Added new base class for map views that have text entry
Changed paths:
A engines/mm/mm1/views/maps/answer_entry.cpp
A engines/mm/mm1/views/maps/answer_entry.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/maps/access_code.cpp
engines/mm/mm1/views/maps/access_code.h
engines/mm/mm1/views/maps/volcano_god.cpp
engines/mm/mm1/views/maps/volcano_god.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 4daa16b9d73..c5ebfeb4a03 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -911,8 +911,8 @@ maps:
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
telgoran1: "AN ELF DRESSED IN ROBES APPROACHES...\n\n"
- telgoran2: """FRIENDS, I AM TELGORAN. THIS SCROLL YOU\nHAVE BROUGHT ME WILL BE VERY HELPFUL"Dh,'(+2500 EXP) HERE'S 1500 GOLD FOR YOUR\nSERVICES. I'LL TELL YOU A SECRET, IF\nTREASURE IS WHAT YOU WANT..."""
- telgoran3: """THE BROTHERS YOU MUST FIND..."Dh,'PORTSMITH AND ALGARY ARE COMBINED."""
+ telgoran2: """FRIENDS, I AM TELGORAN. THIS SCROLL YOU\nHAVE BROUGHT ME WILL BE VERY HELPFUL\n(+2500 EXP) HERE'S 1500 GOLD FOR YOUR\nSERVICES. I'LL TELL YOU A SECRET, IF\nTREASURE IS WHAT YOU WANT..."""
+ telgoran3: """THE BROTHERS YOU MUST FIND...\nPORTSMITH AND ALGARY ARE COMBINED."""
telgoran4: """YOU'RE NOT THE COURIERS!"""
map04:
@@ -1058,7 +1058,7 @@ maps:
map17:
options: "1) RED THORAC 2) BLUE OGRAM\n3) GREEN BAGAR 4) YELLOW LIMRA\n5) PURPLE SAGRAN 6) ORANGE OOLAK\n7) BLACK DRESIDION 8) WHITE DILITHIUM"
- bridge: "A WOODEN BRIDGE EXTENDES ACROSS THE',0Dh,'OCEAN INTO THE MIST. A HOODED FIGURE\nMATERIALIZES, ""TO CROSS YOU MUST EACH\nANSWER A QUESTION, ACCEPT (Y/N)?"""
+ bridge: "A WOODEN BRIDGE EXTENDES ACROSS THE\nOCEAN INTO THE MIST. A HOODED FIGURE\nMATERIALIZES, ""TO CROSS YOU MUST EACH\nANSWER A QUESTION, ACCEPT (Y/N)?"""
color: "WHAT IS YOUR COLOR(1-8)?"
wrong: "WRONG!"
correct: "CORRECT!"
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
index 858fcb42853..c52682069c5 100644
--- a/engines/mm/mm1/views/maps/access_code.cpp
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -37,53 +37,24 @@ namespace Maps {
static const byte OFFSETS1[8] = { 146, 98, 150, 102, 153, 105, 157, 109 };
static const byte OFFSETS2[8] = { 130, 82, 134, 86, 137, 89, 141, 93 };
-AccessCode::AccessCode() : TextView("AccessCode") {
+AccessCode::AccessCode() :
+ AnswerEntry("AccessCode", Common::Point(16, 3), 8) {
_bounds = getLineBounds(20, 24);
}
-bool AccessCode::msgFocus(const FocusMessage &msg) {
- _code = "";
- Sound::sound(SOUND_2);
- return TextView::msgFocus(msg);
-}
-
void AccessCode::draw() {
clearSurface();
-
writeString(0, 1, STRING["maps.map08.enter_code"]);
- writeString(16, 3, _code);
- for (uint i = 0; i < (MAX_CODE_LENGTH - _code.size()); ++i)
- writeChar('.');
-}
-
-bool AccessCode::msgKeypress(const KeypressMessage &msg) {
- if (!isDelayActive()) {
- if (msg.keycode == Common::KEYCODE_RETURN) {
- codeEntered();
- } else if (msg.keycode == Common::KEYCODE_SPACE ||
- (msg.keycode >= Common::KEYCODE_0 &&
- msg.keycode <= Common::KEYCODE_z)) {
- _code += toupper(msg.ascii);
- redraw();
-
- if (_code.size() == MAX_CODE_LENGTH)
- codeEntered();
- } else if (msg.keycode == Common::KEYCODE_BACKSPACE && !_code.empty()) {
- _code.deleteLastChar();
- redraw();
- }
- }
-
- return true;
+ AnswerEntry::draw();
}
-void AccessCode::codeEntered() {
+void AccessCode::answerEntered() {
MM1::Maps::Map &map = *g_maps->_currentMap;
Common::String properCode;
for (int i = 0; i < 10 && map[CODE_OFFSET + i]; ++i)
properCode += map[CODE_OFFSET + i] + 0x1f;
- if (_code == properCode)
+ if (_answer == properCode)
correctCode();
else
incorrectCode();
diff --git a/engines/mm/mm1/views/maps/access_code.h b/engines/mm/mm1/views/maps/access_code.h
index 922184fd6dc..f9c9804a08d 100644
--- a/engines/mm/mm1/views/maps/access_code.h
+++ b/engines/mm/mm1/views/maps/access_code.h
@@ -22,22 +22,15 @@
#ifndef MM1_VIEWS_MAPS_ACCESS_CODE_H
#define MM1_VIEWS_MAPS_ACCESS_CODE_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/maps/answer_entry.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Maps {
-class AccessCode : public TextView {
+class AccessCode : public AnswerEntry {
private:
- Common::String _code;
-
- /**
- * Called when the code has been entered
- */
- void codeEntered();
-
/**
* Correct code entered
*/
@@ -48,13 +41,16 @@ private:
*/
void incorrectCode();
+protected:
+ /**
+ * Called when the code has been entered
+ */
+ void answerEntered() override;
public:
AccessCode();
virtual ~AccessCode() {}
- bool msgFocus(const FocusMessage &msg) override;
void draw() override;
- bool msgKeypress(const KeypressMessage &msg) override;
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/answer_entry.cpp b/engines/mm/mm1/views/maps/answer_entry.cpp
new file mode 100644
index 00000000000..df6e3e827b2
--- /dev/null
+++ b/engines/mm/mm1/views/maps/answer_entry.cpp
@@ -0,0 +1,74 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/answer_entry.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+AnswerEntry::AnswerEntry(const Common::String &name,
+ const Common::Point &pos, size_t maxLength) :
+ TextView(name), _pos(pos), _maxLength(maxLength) {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool AnswerEntry::msgFocus(const FocusMessage &msg) {
+ _answer = "";
+ Sound::sound(SOUND_2);
+ return TextView::msgFocus(msg);
+}
+
+void AnswerEntry::draw() {
+ writeString(_pos.x, _pos.y, _answer);
+ for (uint i = 0; i < (_maxLength - _answer.size()); ++i)
+ writeChar(_blank);
+}
+
+bool AnswerEntry::msgKeypress(const KeypressMessage &msg) {
+ if (!isDelayActive()) {
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ answerEntered();
+ } else if (msg.keycode == Common::KEYCODE_SPACE ||
+ (msg.keycode >= Common::KEYCODE_0 &&
+ msg.keycode <= Common::KEYCODE_z)) {
+ _answer += toupper(msg.ascii);
+ redraw();
+
+ if (_answer.size() == _maxLength)
+ answerEntered();
+
+ } else if (msg.keycode == Common::KEYCODE_BACKSPACE && !_answer.empty()) {
+ _answer.deleteLastChar();
+ redraw();
+ }
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/answer_entry.h b/engines/mm/mm1/views/maps/answer_entry.h
new file mode 100644
index 00000000000..fc49354478f
--- /dev/null
+++ b/engines/mm/mm1/views/maps/answer_entry.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_ANSWER_ENTRY_H
+#define MM1_VIEWS_MAPS_ANSWER_ENTRY_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class AnswerEntry : public TextView {
+private:
+ Common::Point _pos;
+ size_t _maxLength;
+ char _blank = '.';
+protected:
+ Common::String _answer;
+
+ /**
+ * Called when Enter pressed, or maximum length reached
+ */
+ virtual void answerEntered() = 0;
+
+public:
+ AnswerEntry(const Common::String &name,
+ const Common::Point &pos, size_t maxLength);
+ virtual ~AnswerEntry() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
index ee6aa748483..49a0bf3596d 100644
--- a/engines/mm/mm1/views/maps/volcano_god.cpp
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -33,15 +33,8 @@ namespace Maps {
#define ANSWER_OFFSET 636
#define VAL1 641
-VolcanoGod::VolcanoGod() : TextView("VolcanoGod") {
- _bounds = getLineBounds(20, 24);
-}
-
-bool VolcanoGod::msgFocus(const FocusMessage &msg) {
- _answer = "";
- _mode = CHOOSE_OPTION;
- Sound::sound(SOUND_2);
- return TextView::msgFocus(msg);
+VolcanoGod::VolcanoGod() :
+ AnswerEntry("VolcanoGod", Common::Point(9, 3), 8) {
}
void VolcanoGod::draw() {
@@ -54,7 +47,7 @@ void VolcanoGod::draw() {
case ENTER_RESPONSE:
writeString(0, 1, STRING["maps.map11.question"]);
- writeString(9, 3, _answer);
+ AnswerEntry::draw();
break;
default:
@@ -81,21 +74,7 @@ bool VolcanoGod::msgKeypress(const KeypressMessage &msg) {
}
case ENTER_RESPONSE:
- if (msg.keycode == Common::KEYCODE_RETURN) {
- responseEntered();
- } else if (msg.keycode == Common::KEYCODE_SPACE ||
- (msg.keycode >= Common::KEYCODE_0 &&
- msg.keycode <= Common::KEYCODE_z)) {
- _answer += toupper(msg.ascii);
- redraw();
-
- if (_answer.size() == MAX_ANSWER_LENGTH)
- responseEntered();
- } else if (msg.keycode == Common::KEYCODE_BACKSPACE && !_answer.empty()) {
- _answer.deleteLastChar();
- redraw();
- }
- break;
+ return AnswerEntry::msgKeypress(msg);
}
}
@@ -118,7 +97,7 @@ void VolcanoGod::clue() {
g_events->send("Game", GameMessage("UPDATE"));
}
-void VolcanoGod::responseEntered() {
+void VolcanoGod::answerEntered() {
MM1::Maps::Map &map = *g_maps->_currentMap;
Common::String properAnswer;
for (int i = 0; i < 8 && map[MAX_ANSWER_LENGTH + i]; ++i)
diff --git a/engines/mm/mm1/views/maps/volcano_god.h b/engines/mm/mm1/views/maps/volcano_god.h
index 114b3652e45..e82fc6efd6b 100644
--- a/engines/mm/mm1/views/maps/volcano_god.h
+++ b/engines/mm/mm1/views/maps/volcano_god.h
@@ -22,28 +22,29 @@
#ifndef MM1_VIEWS_MAPS_VOLCANO_GOD_H
#define MM1_VIEWS_MAPS_VOLCANO_GOD_H
-#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/views/maps/answer_entry.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Maps {
-class VolcanoGod : public TextView {
+class VolcanoGod : public AnswerEntry {
private:
enum Mode { CHOOSE_OPTION, ENTER_RESPONSE };
Mode _mode = CHOOSE_OPTION;
- Common::String _answer;
void challenge();
void riddle();
void clue();
- void responseEntered();
+
+protected:
+ void answerEntered() override;
+
public:
VolcanoGod();
virtual ~VolcanoGod() {}
- bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 8e026531a13..68caff08f0f 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -51,6 +51,7 @@ MODULE_OBJS := \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
mm1/views/maps/access_code.o \
+ mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
mm1/views/maps/resistances.o \
mm1/views/maps/volcano_god.o \
Commit: 7e24562cb9a55803a085d6bed76f190e352a4c94
https://github.com/scummvm/scummvm/commit/7e24562cb9a55803a085d6bed76f190e352a4c94
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:23+01:00
Commit Message:
MM: MM1: Added Ice Princess view for map 19
Changed paths:
A engines/mm/mm1/views/maps/ice_princess.cpp
A engines/mm/mm1/views/maps/ice_princess.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map19.cpp
engines/mm/mm1/maps/map19.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/access_code.cpp
engines/mm/mm1/views/maps/volcano_god.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c5ebfeb4a03..099cd61bb39 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -842,12 +842,12 @@ maps:
passage_outside: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
map01:
- blacksmith: """B. SMITH',27h,'S WORKSHOP"""
+ blacksmith: """B. SMITH'S WORKSHOP"""
inn: """INN OF PORTSMITH"""
market: """MAID MARION'S MARKET"""
tavern: """ZORELDA'S WATERING HOLE"""
temple: """TEMPLE SUCCUBON"""
- training: """AMAZONIA',27h,'S TRAINING"""
+ training: """AMAZONIA'S TRAINING"""
blacksmith_inside: """BUSILY FORGING A LONG SWORD,AN EXTREMELY\nBEAUTIFUL YOUNG GIRL SAYS WITH A\nSEDUCTIVE SMILE, ""CAN I HELP YOU (Y/N)?"""
inn_inside: "LARA, THE INKEEPERS VOLUPTUOUS\nDAUGHTER, ASKS IF YOU WILL BE SPENDING\nTHE NIGHT... SIGN IN (Y/N)?"
@@ -1076,3 +1076,11 @@ maps:
sign1: "A SIGN POINTING S. READS: BLACKRIDGE N."
sign2: "A SIGN POINTING E. READS: BLACKRIDGE S."
sign3: "A SIGN POINTING E. READS: ERLIQUIN"
+
+ map19:
+ ice_princess: "ON A THRONE ADORNED WITH PRECIOUS GEMS\nTHE ICE PRINCESS SPEAKS,\n""CONQUEROR OF WORLDS, MAKER OF DREAMS\nTHE GREATEST FORCE OF ALL, YET ELUSIVE\nIT SEEMS.""\n\nANSWER:> "
+ incorrect: "WRONG, YOU'RE TOO YOUNG TO UNDERSTAND."
+ correct: "CORRECT!"
+ carving: "CARVED ON A TREE: ""9-9 RAVEN'S LAIR"""
+ cave: "THERE'S A CAVE HERE, ENTER (Y/N)?"
+ stairs_down: "A DESCENDING STAIRCASE IS THE ENTRANCE\nTO A WARRIORS STRONGHOLD, GO IN (Y/N)?"
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index 991be3f4aa1..e9458c6415d 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -117,7 +117,6 @@ void Map18::special02() {
void Map18::special03() {
send(SoundMessage(STRING["maps.map18.ruins"],
[]() {
- Map18 &map = *static_cast<Map18 *>(g_maps->_currentMap);
g_maps->_mapPos = Common::Point(2, 2);
g_maps->changeMap(0xf03, 3);
}
diff --git a/engines/mm/mm1/maps/map19.cpp b/engines/mm/mm1/maps/map19.cpp
index f2a5a0abd72..1d8d65278d5 100644
--- a/engines/mm/mm1/maps/map19.cpp
+++ b/engines/mm/mm1/maps/map19.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 123
+
void Map19::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 6; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[57 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,29 @@ void Map19::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map19::special00() {
+ g_events->addView("IcePrincess");
+}
+
+void Map19::special01() {
+}
+
+void Map19::special02() {
+}
+
+void Map19::special03() {
+}
+
+void Map19::special04() {
+}
+
+void Map19::special05() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map19.h b/engines/mm/mm1/maps/map19.h
index 36cb532dae5..caf199b9fc5 100644
--- a/engines/mm/mm1/maps/map19.h
+++ b/engines/mm/mm1/maps/map19.h
@@ -32,9 +32,19 @@ class Map19 : public Map {
typedef void (Map19:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map19::special00
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+
+ const SpecialFn SPECIAL_FN[6] = {
+ &Map19::special00,
+ &Map19::special01,
+ &Map19::special02,
+ &Map19::special03,
+ &Map19::special04,
+ &Map19::special05
};
public:
Map19() : Map(19, "areab2", 0x703) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 52391a546b6..77594348f3b 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -44,6 +44,7 @@
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/views/maps/arrested.h"
+#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/volcano_god.h"
#include "mm/mm1/views/maps/won_game.h"
@@ -83,9 +84,11 @@ private:
Views::Locations::Training _training;
Views::Maps::Arrested _arrested;
+ Views::Maps::IcePrincess _icePrincess;
Views::Maps::Resistances _resistances;
Views::Maps::VolcanoGod _volcanoGod;
Views::Maps::WonGame _wonGame;
+
Views::Spells::CastSpell _castSpell;
Views::Spells::DetectMagic _detectMagicSpell;
Views::Spells::Duplication _duplicationSpell;
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
index c52682069c5..920a43ad34b 100644
--- a/engines/mm/mm1/views/maps/access_code.cpp
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -30,7 +30,7 @@ namespace Views {
namespace Maps {
#define MAX_CODE_LENGTH 10
-#define CODE_OFFSET 147
+#define ANSWER_OFFSET 147
#define VAL1 163
#define VAL2 408
@@ -51,8 +51,8 @@ void AccessCode::draw() {
void AccessCode::answerEntered() {
MM1::Maps::Map &map = *g_maps->_currentMap;
Common::String properCode;
- for (int i = 0; i < 10 && map[CODE_OFFSET + i]; ++i)
- properCode += map[CODE_OFFSET + i] + 0x1f;
+ for (int i = 0; i < 10 && map[ANSWER_OFFSET + i]; ++i)
+ properCode += map[ANSWER_OFFSET + i] + 0x1f;
if (_answer == properCode)
correctCode();
diff --git a/engines/mm/mm1/views/maps/ice_princess.cpp b/engines/mm/mm1/views/maps/ice_princess.cpp
new file mode 100644
index 00000000000..51d540d8908
--- /dev/null
+++ b/engines/mm/mm1/views/maps/ice_princess.cpp
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/ice_princess.h"
+#include "mm/mm1/maps/map19.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define VAL1 123
+#define ANSWER_OFFSET 167
+
+IcePrincess::IcePrincess() :
+ AnswerEntry("IcePrincess", Common::Point(9, 5), 10) {
+ _bounds = getLineBounds(17, 24);
+}
+
+void IcePrincess::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map19.ice_princess"]);
+}
+
+void IcePrincess::answerEntered() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Common::String properAnswer;
+ map[VAL1] = _answer.size();
+ close();
+
+ for (int i = 0; i < 4; ++i)
+ properAnswer += map[ANSWER_OFFSET + i] & 0x7f + 64;
+
+ if (_answer == properAnswer) {
+ InfoMessage msg(
+ 16, 2, STRING["maps.map19.correct"],
+ []() {
+ g_maps->clearSpecial();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ if (g_globals->_currCharacter->_backpack.indexOf(DIAMOND_KEY_ID) != -1) {
+ g_globals->_treasure[5] = 237;
+ g_events->addAction(KEYBIND_SEARCH);
+ return;
+ }
+ }
+
+ g_globals->_treasure[5] = 240;
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ );
+
+ msg._delaySeconds = 2;
+ send(msg);
+ Sound::sound(SOUND_3);
+ Sound::sound(SOUND_3);
+
+ } else {
+ g_maps->_mapPos.x = 15;
+ g_events->send("Game", GameMessage("UPDATE"));
+ send(SoundMessage(STRING["maps.map19.incorrect"]));
+ }
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/ice_princess.h b/engines/mm/mm1/views/maps/ice_princess.h
new file mode 100644
index 00000000000..87a005ca537
--- /dev/null
+++ b/engines/mm/mm1/views/maps/ice_princess.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_ICE_PRINCESS_H
+#define MM1_VIEWS_MAPS_ICE_PRINCESS_H
+
+#include "mm/mm1/views/maps/answer_entry.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class IcePrincess : public AnswerEntry {
+protected:
+ void answerEntered() override;
+
+public:
+ IcePrincess();
+ virtual ~IcePrincess() {}
+
+ void draw() override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
index 49a0bf3596d..7ce3622cdde 100644
--- a/engines/mm/mm1/views/maps/volcano_god.cpp
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -100,7 +100,7 @@ void VolcanoGod::clue() {
void VolcanoGod::answerEntered() {
MM1::Maps::Map &map = *g_maps->_currentMap;
Common::String properAnswer;
- for (int i = 0; i < 8 && map[MAX_ANSWER_LENGTH + i]; ++i)
+ for (int i = 0; i < 8 && map[ANSWER_OFFSET + i]; ++i)
properAnswer += map[ANSWER_OFFSET + i] + 30;
if (_answer == properAnswer) {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 68caff08f0f..20af0ba937e 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -53,6 +53,7 @@ MODULE_OBJS := \
mm1/views/maps/access_code.o \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
+ mm1/views/maps/ice_princess.o \
mm1/views/maps/resistances.o \
mm1/views/maps/volcano_god.o \
mm1/views/maps/won_game.o \
Commit: 88a63227b8a65a910c154e33c76bb4be83dada82
https://github.com/scummvm/scummvm/commit/88a63227b8a65a910c154e33c76bb4be83dada82
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:23+01:00
Commit Message:
MM: MM1: Remainder of map 19
Changed paths:
engines/mm/mm1/maps/map19.cpp
engines/mm/mm1/maps/map19.h
diff --git a/engines/mm/mm1/maps/map19.cpp b/engines/mm/mm1/maps/map19.cpp
index 1d8d65278d5..c6ed7c8fb55 100644
--- a/engines/mm/mm1/maps/map19.cpp
+++ b/engines/mm/mm1/maps/map19.cpp
@@ -30,6 +30,12 @@ namespace MM1 {
namespace Maps {
#define VAL1 123
+#define VAL2 161
+#define VAL3 162
+#define VAL4 163
+#define VAL5 164
+#define VAL6 165
+#define VAL7 166
void Map19::special() {
// Scan for special actions on the map cell
@@ -56,18 +62,65 @@ void Map19::special00() {
}
void Map19::special01() {
+ send(SoundMessage(
+ STRING["maps.map19.cave"],
+ []() {
+ g_maps->_mapPos = Common::Point(8, 0);
+ g_maps->changeMap(0xa00, 1);
+ }
+ ));
}
void Map19::special02() {
+ send(SoundMessage(
+ STRING["maps.map19.stairs_down"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 1);
+ g_maps->changeMap(0xf02, 3);
+ }
+ ));
}
void Map19::special03() {
+ send(SoundMessage(STRING["maps.map19.carving"]));
}
void Map19::special04() {
+ if (_data[VAL2])
+ g_maps->clearSpecial();
+
+ _data[VAL2]++;
+ _data[VAL4] = 10;
+ _data[VAL5] = 10;
+ _data[VAL7] = 10;
+ _data[VAL6] = 7;
+ encounter();
}
void Map19::special05() {
+ if (_data[VAL3])
+ g_maps->clearSpecial();
+
+ _data[VAL3]++;
+ _data[VAL4] = 10;
+ _data[VAL6] = 7;
+ _data[VAL5] = 1;
+ _data[VAL7] = 1;
+ encounter();
+}
+
+void Map19::encounter() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(5) + 3;
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(_data[VAL7], _data[VAL6]);
+ enc.addMonster(_data[VAL5], _data[VAL4]);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map19.h b/engines/mm/mm1/maps/map19.h
index caf199b9fc5..87db7550a1a 100644
--- a/engines/mm/mm1/maps/map19.h
+++ b/engines/mm/mm1/maps/map19.h
@@ -37,6 +37,7 @@ private:
void special03();
void special04();
void special05();
+ void encounter();
const SpecialFn SPECIAL_FN[6] = {
&Map19::special00,
Commit: 636bee1461f1c4337f3de39ffe838a327f1af200
https://github.com/scummvm/scummvm/commit/636bee1461f1c4337f3de39ffe838a327f1af200
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:23+01:00
Commit Message:
MM: MM1: Added most of map 20
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map20.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 099cd61bb39..e5b08d21059 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1084,3 +1084,14 @@ maps:
carving: "CARVED ON A TREE: ""9-9 RAVEN'S LAIR"""
cave: "THERE'S A CAVE HERE, ENTER (Y/N)?"
stairs_down: "A DESCENDING STAIRCASE IS THE ENTRANCE\nTO A WARRIORS STRONGHOLD, GO IN (Y/N)?"
+
+ map20:
+ passage: "PASSAGE TO PORTSMITH, TAKE IT (Y/N)?"
+ cave: "A CAVE, ENTER (Y/N)?"
+ castle: "CASTLE WHITE WOLF, ENTER (Y/N)?"
+ whistle: "YOUR RUBY WHISTLE BEGINS TO GLOW,\nBLOW IT (0-9 TIMES)?"
+ stairs_down: "STAIRS GOING DOWN, ENTER (Y/N)?"
+ temple: "AN ANCIENT TEMPLE CONVERTED TO A\nSTRONGHOLD HAS NO APPARENT ENTRANCE."
+ peak: "ATOP THIS PEAK LOOKING:\n\nN= A CAVE BEYOND WHITE WOLF.\nE= LARGE BEASTS ABOVE WYVERN PEAKS!\nS= DISTANT UNCHARTED ISLES.\nW= A PIRATE SHIP BEYOND KORIN BLUFFS."
+ sign1: "A SIGN POINTING N. READS: WHITE WOLF"
+ sign2: "A SIGN POINTING S. READS: PORTSMITH"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index ca0f9641d82..b3132090af4 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -92,6 +92,9 @@ enum CharFlags4 {
};
enum CharFlags5 {
+ CHARFLAG5_1 = 1,
+ CHARFLAG5_2 = 2,
+ CHARFLAG5_4 = 4,
CHARFLAG5_8 = 8
};
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index fb33f0a57fb..d24fc019009 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -29,14 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 177
+
void Map20::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 9; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[60 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +47,104 @@ void Map20::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (_states[g_maps->_mapOffset]) {
+ g_maps->clearSpecial();
+ enc.execute();
+
+ } else if (getRandomNumber(100) != 100) {
+ none160();
+
+ } else {
+ int id1 = getRandomNumber(5);
+ int monsterCount = getRandomNumber(13);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, 11);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
}
void Map20::special00() {
+ send(SoundMessage(
+ STRING["maps.map20.stairs_down"],
+ []() {
+ g_maps->_mapPos = Common::Point(1, 15);
+ g_maps->changeMap(0xc03, 1);
+ }
+ ));
+}
+
+void Map20::special01() {
+ send(SoundMessage(
+ STRING["maps.map20.cave"],
+ []() {
+ g_maps->_mapPos = Common::Point(15, 0);
+ g_maps->changeMap(0x51b, 1);
+ }
+ ));
+}
+
+void Map20::special02() {
+ if (_data[VAL1] & 0x80) {
+ g_maps->_mapPos = Common::Point(15, 8);
+ g_maps->changeMap(0xa11, 3);
+
+ } else if (_data[VAL1]) {
+ _data[VAL1] = 0;
+
+ } else {
+ send(SoundMessage(
+ STRING["maps.map20.cave"],
+ [](const Common::KeyState &ks) {
+ Map20 &map = *static_cast<Map20 *>(g_maps->_currentMap);
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+ map[VAL1] = 0xff;
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->close();
+ map[VAL1]++;
+ }
+ }
+ ));
+ }
+}
+
+void Map20::special03() {
+ // TODO
+}
+
+void Map20::special04() {
+ send(SoundMessage(STRING["maps.map20.sign1"]));
+}
+
+void Map20::special05() {
+ send(SoundMessage(STRING["maps.map20.sign2"]));
+}
+
+void Map20::special06() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ g_globals->_currCharacter->_flags[5] |= CHARFLAG5_2;
+ }
+
+ SoundMessage info(0, 0, STRING["maps.map20.peak"]);
+ info._largeMessage = true;
+ send(info);
+}
+
+void Map20::special07() {
+ g_maps->_mapPos.y = 6;
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+void Map20::special08() {
+ g_maps->_mapPos.x = 9;
+ g_events->send("Game", GameMessage("UPDATE"));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map20.h b/engines/mm/mm1/maps/map20.h
index 83b30d82f2a..ccb0583214d 100644
--- a/engines/mm/mm1/maps/map20.h
+++ b/engines/mm/mm1/maps/map20.h
@@ -32,9 +32,25 @@ class Map20 : public Map {
typedef void (Map20:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
- const SpecialFn SPECIAL_FN[1] = {
- &Map20::special00
+ const SpecialFn SPECIAL_FN[9] = {
+ &Map20::special00,
+ &Map20::special01,
+ &Map20::special02,
+ &Map20::special03,
+ &Map20::special04,
+ &Map20::special05,
+ &Map20::special06,
+ &Map20::special07,
+ &Map20::special08
};
public:
Map20() : Map(20, "areab3", 0x101) {}
Commit: d0486d5b881c78a1f97b20acdca926942484560d
https://github.com/scummvm/scummvm/commit/d0486d5b881c78a1f97b20acdca926942484560d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:23+01:00
Commit Message:
MM: MM1: Made game update messages a method in the Map base class
Changed paths:
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map06.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index b9d98b4f675..29c5580dca0 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -104,6 +104,10 @@ void Map::reduceHP() {
g_globals->_party[i]._hpBase /= 2;
}
+void Map::updateGame() {
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 30db2e829b1..27bde73c4f7 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -112,7 +112,7 @@ protected:
/**
* Divides all the party's Hp in half
*/
- void reduceHP();
+ static void reduceHP();
/**
* Many special methods return a 160 key, but it
@@ -122,6 +122,11 @@ protected:
*/
static void none160() {}
+ /**
+ * Updates the game display
+ */
+ static void updateGame();
+
public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
index 3d4287df474..3fc5eb99760 100644
--- a/engines/mm/mm1/maps/map06.cpp
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -84,7 +84,7 @@ void Map06::special() {
pos.y++;
}
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
} else {
checkPartyDead();
}
@@ -161,7 +161,7 @@ void Map06::special07() {
send(SoundMessage(17, 1, STRING["maps.poof"]));
g_maps->_mapPos.x = 10;
g_maps->_mapPos.y = 11;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map06::special09() {
@@ -207,7 +207,7 @@ void Map06::slide() {
send(SoundMessage(16, 1, STRING["maps.map06.slide"]));
_data[VAL2]++;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 4636207251c..181a93a7525 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -92,7 +92,7 @@ void Map07::special02() {
send(SoundMessage(0, 1, STRING["maps.map07.gate"]));
g_maps->_mapPos.y--;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map07::special03() {
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 3251009a9fc..f7cef090743 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -85,12 +85,12 @@ void Map08::special02() {
void Map08::special04() {
g_maps->_mapPos = Common::Point(15, 9);
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map08::special05() {
g_maps->_mapPos = Common::Point(0, 9);
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map08::special06() {
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index ed9535550b7..bb88a38f88b 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -90,7 +90,7 @@ void Map10::special01() {
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->send(SoundMessage(STRING["maps.map10.ranalou3"]));
g_maps->_mapPos = Common::Point(15, 0);
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
}
));
@@ -105,17 +105,17 @@ void Map10::special02() {
void Map10::special17() {
g_maps->_mapPos.y++;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map10::special18() {
g_maps->_mapPos.x++;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map10::special19() {
g_maps->_mapPos.x--;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map10::special20() {
@@ -196,7 +196,7 @@ void Map10::special32() {
void Map10::special33() {
g_maps->_mapPos.x = 15;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 2d44c8514ed..75ebde78403 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -62,7 +62,7 @@ void Map11::special() {
}
send(SoundMessage(STRING["maps.map11.poof"]));
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
}
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index 5fcb5a400ff..92ea8d90d4a 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -193,7 +193,7 @@ void Map12::setPolyhedron(int polyIndex) {
msg,
[]() {
static_cast<Map12 *>(g_maps->_currentMap)->spinPolyhedron(0);
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
));
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index c53bfb9b02e..2bd9811908f 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -170,7 +170,7 @@ void Map15::special06() {
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->send(SoundMessage(STRING["maps.map15.percella1"]));
g_maps->_mapPos = Common::Point(14, 2);
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
}
));
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 41860ef8fd5..18449f8d677 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -67,7 +67,7 @@ void Map17::special() {
} else if (getRandomNumber(30) == 10) {
g_maps->_mapPos = Common::Point(15, 15);
send(SoundMessage(STRING["maps.map17.wave"]));
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
} else {
g_events->addAction(KEYBIND_SEARCH);
@@ -104,7 +104,7 @@ void Map17::askQuestion(uint partyIndex) {
if (partyIndex >= g_globals->_party.size()) {
if (_data[VAL3]) {
g_maps->_mapPos.y = 2;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
} else {
none160();
}
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index d24fc019009..84d1a8b8d44 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -139,12 +139,12 @@ void Map20::special06() {
void Map20::special07() {
g_maps->_mapPos.y = 6;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Map20::special08() {
g_maps->_mapPos.x = 9;
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 0f6db05d709..2edf8d3974b 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -424,7 +424,7 @@ void Maps::changeMap(uint16 id, byte section) {
select(id, section);
loadTiles();
- g_events->send("Game", GameMessage("UPDATE"));
+ updateGame();
}
void Maps::clearSpecial() {
Commit: 128e81c216477267f5ed02d1de4a646ac9fb9939
https://github.com/scummvm/scummvm/commit/128e81c216477267f5ed02d1de4a646ac9fb9939
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:23+01:00
Commit Message:
MM: MM1: Compilation fix
Changed paths:
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 2edf8d3974b..0f6db05d709 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -424,7 +424,7 @@ void Maps::changeMap(uint16 id, byte section) {
select(id, section);
loadTiles();
- updateGame();
+ g_events->send("Game", GameMessage("UPDATE"));
}
void Maps::clearSpecial() {
Commit: b3ffa496ae0235a89f25903bcfa7bbcfd669cd99
https://github.com/scummvm/scummvm/commit/b3ffa496ae0235a89f25903bcfa7bbcfd669cd99
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Fixes for item checks to check both equipped and backpack
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map20.cpp
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index e38c1dd2028..58b990bf593 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -575,5 +575,10 @@ void Character::rest() {
}
}
+bool Character::hasItem(byte itemId) const {
+ return _backpack.indexOf(itemId) != -1 ||
+ _equipped.indexOf(itemId) != -1;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index b3132090af4..f7302f26a0c 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -398,6 +398,11 @@ struct Character {
* Rest the character
*/
void rest();
+
+ /**
+ * Returns true if the character has a given item
+ */
+ bool hasItem(byte itemId) const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 828d24ac98d..f86d1fa0522 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -33,6 +33,7 @@ namespace MM1 {
enum ItemId {
VELLUM_SCROLL_ID = 231,
+ RUBY_WHISTLE_ID = 232,
BRONZE_KEY_ID = 237,
DIAMOND_KEY_ID = 240
};
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 9097d9d7a62..483cf3dd489 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -66,12 +66,9 @@ void Map03::special01() {
bool hasScroll = false;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- for (uint j = 0; j < c._equipped.size() && !hasScroll; ++j) {
- if (c._equipped[i]._id == 231) {
- hasScroll = true;
- c._gold += 1500;
- break;
- }
+ if (c.hasItem(VELLUM_SCROLL_ID)) {
+ hasScroll = true;
+ c._gold += 1500;
}
}
@@ -81,12 +78,12 @@ void Map03::special01() {
g_globals->_currCharacter = &c;
c._exp += 2500;
- for (uint j = 0; j < c._equipped.size(); ++j) {
- if (c._equipped[j]._id == 231) {
- c._equipped.removeAt(j);
- break;
- }
- }
+ int idx = c._equipped.indexOf(VELLUM_SCROLL_ID);
+ if (idx != -1)
+ c._equipped.removeAt(idx);
+ idx = c._backpack.indexOf(VELLUM_SCROLL_ID);
+ if (idx != -1)
+ c._backpack.removeAt(idx);
}
InfoMessage info1(
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 23c8d45c98b..b26b23ac3a6 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -73,7 +73,7 @@ void Map04::special01() {
bool hasScroll = false;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- if (c._equipped.indexOf(231) != -1) {
+ if (c.hasItem(VELLUM_SCROLL_ID) != -1) {
hasScroll = true;
c._gold += 1500;
break;
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index f64b234e3c7..46b15eda351 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -191,7 +191,7 @@ void Map05::showMessage(const Common::String &msg) {
bool Map05::hasScroll() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
const Character &c = g_globals->_party[i];
- if (c._equipped.indexOf(VELLUM_SCROLL_ID) != -1)
+ if (c.hasItem(VELLUM_SCROLL_ID))
return true;
}
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 181a93a7525..9077b4cbf16 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -80,9 +80,9 @@ void Map07::special02() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
const Character &c = g_globals->_party[i];
- for (uint j = 0; j < c._equipped.size(); ++j) {
- if (c._equipped[j]._id >= BRONZE_KEY_ID &&
- c._equipped[j]._id <= DIAMOND_KEY_ID) {
+ for (byte itemId = BRONZE_KEY_ID;
+ itemId <= DIAMOND_KEY_ID; ++itemId) {
+ if (c.hasItem(itemId)) {
// Someone has a key
none160();
return;
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index 84d1a8b8d44..eb32e6ab898 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -115,6 +115,10 @@ void Map20::special02() {
}
void Map20::special03() {
+ bool hasWhistle = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasWhistle; ++i)
+ hasWhistle = g_globals->_party[i].hasItem(RUBY_WHISTLE_ID);
+
// TODO
}
Commit: d842c4da33f2c505a4a914217d4673679d7689d8
https://github.com/scummvm/scummvm/commit/d842c4da33f2c505a4a914217d4673679d7689d8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Remainder of map 20
Changed paths:
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map20.cpp
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index f7302f26a0c..18030828a1e 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -68,7 +68,10 @@ enum CharFlags0 {
CHARFLAG0_COURIER2 = 2,
CHARFLAG0_COURIER3 = 4,
CHARFLAG0_ZOM_CLUE = 8,
- CHARFLAG0_ZAM_CLUE = 0x10
+ CHARFLAG0_ZAM_CLUE = 0x10,
+ CHARFLAG0_20 = 0x20,
+ CHARFLAG0_40 = 0x40,
+ CHARFLAG0_80 = 0x80
};
enum CharFlags1 {
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index eb32e6ab898..ee9b2231b25 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -119,7 +119,46 @@ void Map20::special03() {
for (uint i = 0; i < g_globals->_party.size() && !hasWhistle; ++i)
hasWhistle = g_globals->_party[i].hasItem(RUBY_WHISTLE_ID);
- // TODO
+ if (!hasWhistle) {
+ send(SoundMessage(STRING["maps.map20.castle"]));
+ return;
+ }
+
+ send(
+ SoundMessage(STRING["maps.map20.castle"],
+ [](const Common::KeyState &) {
+ g_events->close();
+ g_events->send(SoundMessage(
+ STRING["maps.map20.whistle"],
+ [](const Common::KeyState &ks) {
+ if (ks.keycode == Common::KEYCODE_0) {
+ g_events->close();
+ none160();
+ } else if (ks.keycode == Common::KEYCODE_2) {
+ g_events->close();
+ g_events->send(SoundMessage(
+ STRING["maps.map20.stairs_down"],
+ []() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ g_globals->_currCharacter->_flags[0] |= CHARFLAG0_20 | CHARFLAG0_40;
+ }
+
+ g_maps->_mapPos = Common::Point(8, 8);
+ g_maps->changeMap(0xf04, 3);
+ }
+ ));
+
+ } else if (ks.keycode >= Common::KEYCODE_1 &&
+ ks.keycode <= Common::KEYCODE_9) {
+ g_events->close();
+ g_maps->_mapPos = Common::Point(8, 5);
+ g_maps->changeMap(0x604, 1);
+ }
+ }
+ ));
+ }
+ ));
}
void Map20::special04() {
Commit: 8fe5bd80ca059fe4113282d5110c8c12a99a1141
https://github.com/scummvm/scummvm/commit/8fe5bd80ca059fe4113282d5110c8c12a99a1141
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Added map 21
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map21.cpp
engines/mm/mm1/maps/map21.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index e5b08d21059..a87170cd7c9 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1095,3 +1095,25 @@ maps:
peak: "ATOP THIS PEAK LOOKING:\n\nN= A CAVE BEYOND WHITE WOLF.\nE= LARGE BEASTS ABOVE WYVERN PEAKS!\nS= DISTANT UNCHARTED ISLES.\nW= A PIRATE SHIP BEYOND KORIN BLUFFS."
sign1: "A SIGN POINTING N. READS: WHITE WOLF"
sign2: "A SIGN POINTING S. READS: PORTSMITH"
+
+ map21:
+ trivia_island: "TRIVIA ISLAND! 500 GOLD, ENTER (Y/N)?"
+ not_enough_gold: "NOT ENOUGH GOLD!"
+ ghostship: "PIRATE GHOSTSHIP ANARCHIST!"
+ who_be_ye: "WHO BE YE?"
+ free_trivia: "FREE TRIVIA CHANCE, PULL BRANCH (Y/N)?"
+ questions:
+ 0: "WHO RULES CASTLE W.W.?"
+ 1: "WHO IS THE VOLUPTUOUS ONE?"
+ 2: "WHO'S LOST SIGHT?"
+ 3: "WHERE'S THE VERY LATEST?"
+ 4: "WHO BE YE?"
+ answers:
+ 0: "LORD IRONFIST"
+ 1: "LAURA"
+ 2: "OG"
+ 3: "ERLIQUIN"
+ 4: "I BE ME"
+ correct: "CORRECT! +50 GEMS"
+ incorrect: "WRONG!"
+ answer: "ANSWER:> .............."
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 18030828a1e..46d3b58a3d5 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -101,6 +101,10 @@ enum CharFlags5 {
CHARFLAG5_8 = 8
};
+enum CharFlags7 {
+ CHARFLAG7_20 = 0x20
+};
+
enum CharFlags11 {
CHARFLAG11_GOT_ENDURANCE = 1,
CHARFLAG11_2 = 2,
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index ee9b2231b25..f1ab4cc1024 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -48,7 +48,7 @@ void Map20::special() {
}
}
- if (_states[g_maps->_mapOffset]) {
+ if (_states[g_maps->_mapOffset] != 0xff) {
g_maps->clearSpecial();
enc.execute();
diff --git a/engines/mm/mm1/maps/map21.cpp b/engines/mm/mm1/maps/map21.cpp
index 3cc811d87e1..b1d57e139db 100644
--- a/engines/mm/mm1/maps/map21.cpp
+++ b/engines/mm/mm1/maps/map21.cpp
@@ -29,14 +29,19 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 159
+#define VAL2 160
+#define TRIVIA_COST 500
+
void Map21::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 8; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[59 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +49,107 @@ void Map21::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (_states[g_maps->_mapOffset] != 0xff) {
+ g_maps->clearSpecial();
+ enc.execute();
+
+ } else if (getRandomNumber(100) != 100) {
+ if (getRandomNumber(200) != 192)
+ none160();
+ return;
+
+ } else {
+ int id1 = getRandomNumber(14);
+ int monsterCount = getRandomNumber(13);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, 11);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
}
void Map21::special00() {
+ g_maps->clearSpecial();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ g_globals->_currCharacter->_flags[7] |= CHARFLAG7_20;
+ }
+
+ SoundMessage msg(
+ STRING["maps.map21.ghostship"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ enc.clearMonsters();
+ for (int i = 0; i < 8; ++i)
+ enc.addMonster(12, 12);
+ enc.addMonster(13, 12);
+ for (int i = 9; i < 13; ++i)
+ enc.addMonster(3, 8);
+
+ enc._levelIndex = 80;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc._flag = true;
+ enc.execute();
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
+}
+
+void Map21::special01() {
+ send(SoundMessage(
+ STRING["maps.map21.free_trivia"],
+ []() {
+ Map21 &map = *static_cast<Map21 *>(g_maps->_currentMap);
+ map[VAL2]++;
+ }
+ ));
+}
+
+void Map21::special02() {
+ send(SoundMessage(
+ STRING["maps.map21.trivia_island"],
+ [](const Common::KeyState &ks) {
+ Map21 &map = *static_cast<Map21 *>(g_maps->_currentMap);
+
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ if (g_globals->_currCharacter->_gold >= TRIVIA_COST) {
+ c._gold -= 500;
+ g_maps->clearSpecial();
+ return;
+ }
+ }
+
+ g_events->send(SoundMessage(STRING["maps.map21.not_enough_gold"]));
+ g_maps->_mapPos.y++;
+ updateGame();
+
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->close();
+ g_maps->_mapPos.y++;
+ updateGame();
+ }
+ }
+ ));
+}
+
+void Map21::special03() {
+ send("Trivia", 0);
+}
+
+void Map21::special04() {
+ send("Trivia", 0);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map21.h b/engines/mm/mm1/maps/map21.h
index 367ccce7307..9d8e6c69a71 100644
--- a/engines/mm/mm1/maps/map21.h
+++ b/engines/mm/mm1/maps/map21.h
@@ -32,9 +32,20 @@ class Map21 : public Map {
typedef void (Map21:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map21::special00
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+
+ const SpecialFn SPECIAL_FN[8] = {
+ &Map21::special00,
+ &Map21::special01,
+ &Map21::special02,
+ &Map21::special03,
+ &Map21::special04,
+ &Map21::special04,
+ &Map21::special04,
+ &Map21::special04
};
public:
Map21() : Map(21, "areab4", 0xD03) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 77594348f3b..3cdf73f2cd5 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -46,6 +46,7 @@
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/resistances.h"
+#include "mm/mm1/views/maps/trivia.h"
#include "mm/mm1/views/maps/volcano_god.h"
#include "mm/mm1/views/maps/won_game.h"
#include "mm/mm1/views/spells/cast_spell.h"
@@ -86,6 +87,7 @@ private:
Views::Maps::Arrested _arrested;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Resistances _resistances;
+ Views::Maps::Trivia _trivia;
Views::Maps::VolcanoGod _volcanoGod;
Views::Maps::WonGame _wonGame;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 20af0ba937e..a25406fb161 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -55,6 +55,7 @@ MODULE_OBJS := \
mm1/views/maps/arrested.o \
mm1/views/maps/ice_princess.o \
mm1/views/maps/resistances.o \
+ mm1/views/maps/trivia.o \
mm1/views/maps/volcano_god.o \
mm1/views/maps/won_game.o \
mm1/views/spells/spell_view.o \
Commit: a587ae6e2792713c3cc157c3fcf0d1809242ca69
https://github.com/scummvm/scummvm/commit/a587ae6e2792713c3cc157c3fcf0d1809242ca69
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Added map 22
Changed paths:
A engines/mm/mm1/views/maps/trivia.cpp
A engines/mm/mm1/views/maps/trivia.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map22.cpp
engines/mm/mm1/maps/map22.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index a87170cd7c9..cdbf6c34293 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1117,3 +1117,13 @@ maps:
correct: "CORRECT! +50 GEMS"
incorrect: "WRONG!"
answer: "ANSWER:> .............."
+
+ map22:
+ ambush: "AMBUSH!"
+ wagons: "DESERTED MERCHANT WAGONS, SEARCH (Y/N)?"
+ poison: "ARGHHH... POISON!"
+ today_spells: "TODAY SPELLS!"
+ today_might: "TODAY MIGHT!"
+ fountain: "A FOUNTAIN SPEAKS:\n""WILL THE PARTY DRINK (Y/N)?"""
+ chest: "YOU FOUND A CHEST UPON WHICH AN\nINSCRIPTION READS: PROPERTY OF XX!XX!\nINSIDE YOU FOUND A RUBY WHISTLE, 2000\nGOLD AND A NOTE:\nTHE STRONGHOLD LIES AT B-3,14-2\nBLOW TWICE TO ENTER."
+ roadsign: "ROADSIGN: SORPIGAL S.17, W.1, N.2"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 46d3b58a3d5..dfd3233a913 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -69,7 +69,7 @@ enum CharFlags0 {
CHARFLAG0_COURIER3 = 4,
CHARFLAG0_ZOM_CLUE = 8,
CHARFLAG0_ZAM_CLUE = 0x10,
- CHARFLAG0_20 = 0x20,
+ CHARFLAG0_FOUND_CHEST = 0x20,
CHARFLAG0_40 = 0x40,
CHARFLAG0_80 = 0x80
};
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index f1ab4cc1024..bdd2b388d35 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -141,7 +141,7 @@ void Map20::special03() {
[]() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
g_globals->_currCharacter = &g_globals->_party[i];
- g_globals->_currCharacter->_flags[0] |= CHARFLAG0_20 | CHARFLAG0_40;
+ g_globals->_currCharacter->_flags[0] |= CHARFLAG0_FOUND_CHEST | CHARFLAG0_40;
}
g_maps->_mapPos = Common::Point(8, 8);
diff --git a/engines/mm/mm1/maps/map22.cpp b/engines/mm/mm1/maps/map22.cpp
index 45a63b430b1..36b55ca4b3b 100644
--- a/engines/mm/mm1/maps/map22.cpp
+++ b/engines/mm/mm1/maps/map22.cpp
@@ -29,14 +29,18 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define WHISTLE_COUNT 107
+
+static const byte MONSTER_ID1[5] = { 13, 12, 13, 12, 11 };
+static const byte MONSTER_ID2[5] = { 6, 6, 5, 5, 4 };
+
void Map22::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 14; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[65 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +48,131 @@ void Map22::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map22::special00() {
+ bool hasFlags = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasFlags; ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ hasFlags = ((g_globals->_currCharacter->_flags[0] &
+ (CHARFLAG0_ZAM_CLUE | CHARFLAG0_ZOM_CLUE)) ==
+ (CHARFLAG0_ZAM_CLUE | CHARFLAG0_ZOM_CLUE));
+ }
+
+ if (!hasFlags) {
+ none160();
+ return;
+ }
+
+ Sound::sound(SOUND_3);
+ send(InfoMessage(STRING["maps.map22.chest"]));
+
+ for (uint i = 0; i < g_globals->_party.size() && !hasFlags; ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ // Remove the clue flags
+ c._flags[0] = (c._flags[0] & ~(CHARFLAG0_ZAM_CLUE | CHARFLAG0_ZOM_CLUE)) |
+ CHARFLAG0_FOUND_CHEST;
+
+ // Add amulet to player
+ if (!c._backpack.full()) {
+ _data[WHISTLE_COUNT]++;
+ c._backpack.add(RUBY_WHISTLE_ID, 200);
+ }
+ }
+
+ if (!_data[WHISTLE_COUNT]) {
+ // Entire party's inventory full. So screw it, replace
+ // the last item in the last character's backpack
+ g_globals->_currCharacter->_backpack.removeAt(INVENTORY_COUNT - 1);
+ g_globals->_currCharacter->_backpack.add(RUBY_WHISTLE_ID, 192);
+ }
+
+ g_globals->_currCharacter->_gold += 5000;
+}
+
+void Map22::special01() {
+ send(SoundMessage(STRING["maps.map22.roadsign"]));
+}
+
+void Map22::special02() {
+ send(SoundMessage(
+ STRING["maps.map22.wagons"],
+ []() {
+ g_maps->clearSpecial();
+ if (g_maps->_mapPos.x == 5) {
+ g_globals->_treasure[5] = 234;
+ g_events->addAction(KEYBIND_SEARCH);
+
+ } else {
+ InfoMessage msg1(
+ 16, 2, STRING["maps.map22.ambush"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(3);
+ int idx = getRandomNumber(5) - 1;
+ const int id1 = MONSTER_ID1[idx];
+ const int id2 = MONSTER_ID2[idx];
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, id2);
+
+ enc._levelIndex = 32;
+ enc._flag = true;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc.execute();
+ }
+ );
+ msg1._delaySeconds = 2;
+ g_events->send(msg1);
+ }
+ }
+ ));
+}
+
+void Map22::special08() {
+ send(SoundMessage(
+ STRING["maps.map22.fountain"],
+ []() {
+ switch (g_maps->_mapPos.x) {
+ case 8:
+ // Add might
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._might._current += 50;
+
+ Sound::sound(SOUND_3);
+ g_events->send(SoundMessage(STRING["maps.map22.today_might"]));
+ break;
+
+ case 9:
+ // Add spell levels
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._spellLevel._current += 7;
+
+ Sound::sound(SOUND_3);
+ g_events->send(SoundMessage(STRING["maps.map22.today_spells"]));
+ break;
+
+ default:
+ // Poison
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._condition & BAD_CONDITION))
+ c._condition |= POISONED;
+ }
+
+ Sound::sound(SOUND_3);
+ g_events->send(SoundMessage(STRING["maps.map22.poison"]));
+ break;
+ }
+ }
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map22.h b/engines/mm/mm1/maps/map22.h
index f77e92e904f..94453ccc86d 100644
--- a/engines/mm/mm1/maps/map22.h
+++ b/engines/mm/mm1/maps/map22.h
@@ -32,9 +32,25 @@ class Map22 : public Map {
typedef void (Map22:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special08();
- const SpecialFn SPECIAL_FN[1] = {
- &Map22::special00
+ const SpecialFn SPECIAL_FN[14] = {
+ &Map22::special00,
+ &Map22::special01,
+ &Map22::special02,
+ &Map22::special02,
+ &Map22::special02,
+ &Map22::special02,
+ &Map22::special02,
+ &Map22::special02,
+ &Map22::special08,
+ &Map22::special08,
+ &Map22::special08,
+ &Map22::special08,
+ &Map22::special08,
+ &Map22::special08
};
public:
Map22() : Map(22, "areac1", 0x304) {}
diff --git a/engines/mm/mm1/views/maps/trivia.cpp b/engines/mm/mm1/views/maps/trivia.cpp
new file mode 100644
index 00000000000..1355f8a3f41
--- /dev/null
+++ b/engines/mm/mm1/views/maps/trivia.cpp
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/trivia.h"
+#include "mm/mm1/maps/map21.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define VAL1 159
+#define VAL2 160
+
+Trivia::Trivia() :
+ AnswerEntry("Trivia", Common::Point(9, 5), 14) {
+}
+
+bool Trivia::msgValue(const ValueMessage &msg) {
+ _question = STRING[Common::String::format(
+ "maps.map21.questions.%d", msg._value)];
+ _correctAnswer = STRING[Common::String::format(
+ "maps.map21.questions.%d", msg._value)];
+
+ open();
+ return true;
+}
+
+void Trivia::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map19.ice_princess"]);
+}
+
+void Trivia::answerEntered() {
+ if (_answer == _correctAnswer) {
+ send(InfoMessage(STRING["maps.map21.correct"]));
+ g_globals->_party[0]._gems += 50;
+ Sound::sound(SOUND_3);
+
+ } else {
+ g_maps->_mapPos.x = 15;
+ g_events->send("Game", GameMessage("UPDATE"));
+ send(InfoMessage(STRING["maps.map19.incorrect"]));
+ }
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/trivia.h b/engines/mm/mm1/views/maps/trivia.h
new file mode 100644
index 00000000000..e84be214995
--- /dev/null
+++ b/engines/mm/mm1/views/maps/trivia.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_TRIVIA_H
+#define MM1_VIEWS_MAPS_TRIVIA_H
+
+#include "mm/mm1/views/maps/answer_entry.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Trivia : public AnswerEntry {
+private:
+ Common::String _question, _correctAnswer;
+protected:
+ void answerEntered() override;
+
+public:
+ Trivia();
+ virtual ~Trivia() {}
+
+ bool msgValue(const ValueMessage &msg) override;
+ void draw() override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
Commit: 1a5ddb0efed4b710ae9f16e5a0baa9d467c4cb23
https://github.com/scummvm/scummvm/commit/1a5ddb0efed4b710ae9f16e5a0baa9d467c4cb23
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Fixer compiler warnings
Changed paths:
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map21.cpp
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index b26b23ac3a6..d3a2b673c77 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -73,7 +73,7 @@ void Map04::special01() {
bool hasScroll = false;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- if (c.hasItem(VELLUM_SCROLL_ID) != -1) {
+ if (c.hasItem(VELLUM_SCROLL_ID)) {
hasScroll = true;
c._gold += 1500;
break;
diff --git a/engines/mm/mm1/maps/map21.cpp b/engines/mm/mm1/maps/map21.cpp
index b1d57e139db..f65221eaf39 100644
--- a/engines/mm/mm1/maps/map21.cpp
+++ b/engines/mm/mm1/maps/map21.cpp
@@ -116,8 +116,6 @@ void Map21::special02() {
send(SoundMessage(
STRING["maps.map21.trivia_island"],
[](const Common::KeyState &ks) {
- Map21 &map = *static_cast<Map21 *>(g_maps->_currentMap);
-
if (ks.keycode == Common::KEYCODE_y) {
g_events->close();
Commit: 378a12922a7bc793d4dba75845649c5c82b27ad7
https://github.com/scummvm/scummvm/commit/378a12922a7bc793d4dba75845649c5c82b27ad7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Added gypsy view for map 23
Changed paths:
A engines/mm/mm1/views/maps/gypsy.cpp
A engines/mm/mm1/views/maps/gypsy.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/maps/map24.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index cdbf6c34293..ca7e9032763 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1127,3 +1127,27 @@ maps:
fountain: "A FOUNTAIN SPEAKS:\n""WILL THE PARTY DRINK (Y/N)?"""
chest: "YOU FOUND A CHEST UPON WHICH AN\nINSCRIPTION READS: PROPERTY OF XX!XX!\nINSIDE YOU FOUND A RUBY WHISTLE, 2000\nGOLD AND A NOTE:\nTHE STRONGHOLD LIES AT B-3,14-2\nBLOW TWICE TO ENTER."
roadsign: "ROADSIGN: SORPIGAL S.17, W.1, N.2"
+
+ map23:
+ cave: "THERE'S A CAVE HERE, ENTER (Y/N)?"
+ passage: "A CAVERNOUS PASSAGE LEADS TO SORPIGAL,\nTAKE IT (Y/N)?"
+ pit: "A PIT!...."
+ levitation: "YOUR LEVITATION SAVED YOU!"
+ ambush: "AN AMBUSH!"
+ column: "A GLOWING WHITE COLUMN, TOUCH IT (Y/N)?"
+ statues: "STATUES BLOCK THE PATH,SMASH THEM (Y/N)?"
+ fountain: "A STRANGE FOUNTAIN, DRINK (Y/N)?"
+ cheers: "CHEERS!"
+ avalanche: "AVALANCHE!"
+ look_out: "LOOK OUT!"
+ gypsy: "A TOOTHLESS GYPSY SEER ASKS,""WHO WOULD\nLIKE TO HEAR THEIR SIGN (1-6)?"""
+ your_sign_is: """YOUR SIGN IS THE"
+ signs:
+ 0: "RED THORAC"""
+ 1: "BLUE OGRAM"""
+ 2: "GREEN BAGAR"""
+ 3: "YELLOW LIMRA"""
+ 4: "PURPLE SAGRAN"""
+ 5: "ORANGE OOLAK"""
+ 6: "BLACK DRESIDION"""
+ 7: "WHITE DILITHIUM"""
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index dfd3233a913..84fc678309a 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -90,6 +90,8 @@ enum CharFlags2 {
};
enum CharFlags4 {
+ CHARFLAG4_ASSIGNED = 8,
+ CHARFLAG4_SIGN = 7,
CHARFLAG4_COLOR = 0xf,
CHARFLAG4_80 = 0x80
};
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index 1eb99e5b290..fb8b6c2b8d2 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map24::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 14; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[65 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,61 @@ void Map24::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
+
g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+ InfoMessage msg(
+ 14, 2, STRING["maps.map24.look_out"],
+ []() {
+ g_globals->_encounters.execute();
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
}
void Map24::special00() {
+ send(SoundMessage(
+ STRING["maps.map24.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(12, 0);
+ g_maps->changeMap(0x604, 1);
+ }
+ ));
+}
+
+void Map24::special01() {
+ send(SoundMessage(
+ STRING["maps.map24.cave"],
+ []() {
+ g_maps->_mapPos = Common::Point(2, 0);
+ g_maps->changeMap(1, 1);
+ }
+ ));
+}
+
+void Map24::special02() {
+ g_events->addView("Gypsy");
+}
+
+void Map24::special03() {
+}
+
+void Map24::special08() {
+}
+
+void Map24::special09() {
+}
+
+void Map24::special10() {
+}
+
+void Map24::special11() {
+}
+
+void Map24::special12() {
+}
+
+void Map24::special13() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map24.h b/engines/mm/mm1/maps/map24.h
index 632b45edd10..9c51cd0b601 100644
--- a/engines/mm/mm1/maps/map24.h
+++ b/engines/mm/mm1/maps/map24.h
@@ -32,9 +32,31 @@ class Map24 : public Map {
typedef void (Map24:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
- const SpecialFn SPECIAL_FN[1] = {
- &Map24::special00
+ const SpecialFn SPECIAL_FN[14] = {
+ &Map24::special00,
+ &Map24::special01,
+ &Map24::special02,
+ &Map24::special03,
+ &Map24::special03,
+ &Map24::special03,
+ &Map24::special03,
+ &Map24::special03,
+ &Map24::special08,
+ &Map24::special09,
+ &Map24::special10,
+ &Map24::special11,
+ &Map24::special12,
+ &Map24::special13
};
public:
Map24() : Map(24, "areac3", 0x904) {}
diff --git a/engines/mm/mm1/views/maps/gypsy.cpp b/engines/mm/mm1/views/maps/gypsy.cpp
new file mode 100644
index 00000000000..2e69ae95785
--- /dev/null
+++ b/engines/mm/mm1/views/maps/gypsy.cpp
@@ -0,0 +1,111 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/gypsy.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define VAL1 123
+#define ANSWER_OFFSET 167
+
+Gypsy::Gypsy() : TextView("Gypsy") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Gypsy::msgFocus(const FocusMessage &msg) {
+ TextView::msgFocus(msg);
+ modeChanged(true);
+ return true;
+}
+
+bool Gypsy::msgUnfocus(const UnfocusMessage &msg) {
+ TextView::msgUnfocus(msg);
+ modeChanged(false);
+ return true;
+}
+
+void Gypsy::charSelected(uint charIndex) {
+ if (charIndex < g_globals->_party.size()) {
+ _character = &g_globals->_party[charIndex];
+
+ if (!(_character->_flags[4] & CHARFLAG4_ASSIGNED)) {
+ _character->_flags[4] = CHARFLAG4_ASSIGNED |
+ (getRandomNumber(8) - 1);
+ }
+
+ redraw();
+ }
+}
+
+void Gypsy::modeChanged(bool allowSelection) {
+ if (allowSelection)
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_PARTY_MENUS);
+ else
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+
+}
+
+void Gypsy::draw() {
+ clearSurface();
+ if (!_character) {
+ writeString(0, 1, STRING["maps.map24.gypsy"]);
+ } else {
+ Common::String line = Common::String::format("%s %s",
+ STRING["maps.map24.your_sign_is"].c_str(),
+ STRING[Common::String::format("maps.map24.signs.%d",
+ _character->_flags[4] & CHARFLAG4_SIGN)].c_str()
+ );
+ }
+}
+
+bool Gypsy::msgKeypress(const KeypressMessage &msg) {
+ if (_character) {
+ _character = nullptr;
+ modeChanged(true);
+ } else if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= Common::KEYCODE_6) {
+ uint idx = msg.keycode - Common::KEYCODE_1;
+ charSelected(idx);
+ } else {
+ close();
+ }
+
+ return true;
+}
+
+bool Gypsy::msgAction(const ActionMessage &msg) {
+ if (_character && msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ uint idx = msg._action - KEYBIND_VIEW_PARTY1;
+ charSelected(idx);
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/gypsy.h b/engines/mm/mm1/views/maps/gypsy.h
new file mode 100644
index 00000000000..1904a286403
--- /dev/null
+++ b/engines/mm/mm1/views/maps/gypsy.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_GYPSY_H
+#define MM1_VIEWS_MAPS_GYPSY_H
+
+#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/data/character.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Gypsy : public TextView {
+private:
+ Character *_character = nullptr;
+
+ void charSelected(uint charIndex);
+ void modeChanged(bool allowSelection);
+public:
+ Gypsy();
+ virtual ~Gypsy() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index a25406fb161..b12703dca5a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -53,6 +53,7 @@ MODULE_OBJS := \
mm1/views/maps/access_code.o \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
+ mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
mm1/views/maps/resistances.o \
mm1/views/maps/trivia.o \
Commit: 347233c82a5ed4f42122b134ff999f9b49c1850e
https://github.com/scummvm/scummvm/commit/347233c82a5ed4f42122b134ff999f9b49c1850e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Add map 23
Changed paths:
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map23.h
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/maps/map24.h
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 84fc678309a..8ea176e5d2c 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -292,14 +292,8 @@ union Resistances {
void synchronize(Common::Serializer &s);
};
-struct Character {
- char _name[16] = { 0 };
- Sex _sex = MALE;
- Alignment _alignmentInitial = GOOD;
- Alignment _alignment = GOOD;
- Race _race = HUMAN;
- CharacterClass _class = NONE;
-
+struct PrimaryAttributes {
+public:
AttributePair _intelligence;
AttributePair _might;
AttributePair _personality;
@@ -307,8 +301,26 @@ struct Character {
AttributePair _speed;
AttributePair _accuracy;
AttributePair _luck;
-
AttributePair _level;
+
+ AttributePair &getAttribute(uint i) {
+ return *_attributes[i];
+ }
+private:
+ AttributePair *_attributes[8] = {
+ &_intelligence, &_might, &_personality, &_endurance,
+ &_speed, &_accuracy, &_luck, &_level
+ };
+};
+
+struct Character : public PrimaryAttributes {
+ char _name[16] = { 0 };
+ Sex _sex = MALE;
+ Alignment _alignmentInitial = GOOD;
+ Alignment _alignment = GOOD;
+ Race _race = HUMAN;
+ CharacterClass _class = NONE;
+
AttributePair _age;
AttributePair16 _sp;
AttributePair _spellLevel;
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index 4dc833ff539..7af83534b4f 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -29,14 +29,16 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 107
+#define VAL2 108
+
void Map23::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 14; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[65 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +46,159 @@ void Map23::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
+
g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+ InfoMessage msg(
+ 14, 2, STRING["maps.map23.look_out"],
+ []() {
+ g_globals->_encounters.execute();
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
}
void Map23::special00() {
+ send(SoundMessage(
+ STRING["maps.map23.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(12, 0);
+ g_maps->changeMap(0x604, 1);
+ }
+ ));
+}
+
+void Map23::special01() {
+ send(SoundMessage(
+ STRING["maps.map23.cave"],
+ []() {
+ g_maps->_mapPos = Common::Point(2, 0);
+ g_maps->changeMap(1, 1);
+ }
+ ));
+}
+
+void Map23::special02() {
+ g_events->addView("Gypsy");
+}
+
+void Map23::special03() {
+ if (g_globals->_activeSpells._s.levitate) {
+ Common::String line1 = Common::String::format("%s %s",
+ STRING["maps.map23.pit"].c_str(),
+ STRING["maps.map23.levitation"].c_str()
+ );
+
+ send(SoundMessage(line1));
+
+ } else {
+ reduceHP();
+
+ Common::String line1 = Common::String::format("%s %s",
+ STRING["maps.map23.pit"].c_str(),
+ STRING["maps.map23.ambush"].c_str()
+ );
+ SoundMessage msg(line1,
+ []() {
+ g_globals->_encounters.execute();
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
+ }
+}
+
+void Map23::special08() {
+ send(SoundMessage(
+ STRING["maps.map19.column"],
+ []() {
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(15), getRandomNumber(15));
+ updateGame();
+ }
+ ));
+}
+
+void Map23::special09() {
+ send(SoundMessage(
+ STRING["maps.map19.statues"],
+ []() {
+ Map23 &map = *static_cast<Map23 *>(g_maps->_currentMap);
+ Game::Encounter &enc = g_globals->_encounters;
+
+ g_maps->clearSpecial();
+ map._walls[32]--;
+
+ enc.clearMonsters();
+ for (int i = 0; i < 6; ++i)
+ enc.addMonster(2, 4);
+
+ enc._levelIndex = 80;
+ enc._flag = true;
+ enc.execute();
+ }
+ ));
+}
+
+void Map23::special10() {
+ if (_data[VAL1]) {
+ if (g_maps->_forwardMask != DIRMASK_E) {
+ g_maps->clearSpecial();
+ return;
+ }
+ } else {
+ _data[VAL1] = 1;
+ }
+
+ fountain();
+}
+
+void Map23::special11() {
+ if (_data[VAL2]) {
+ if (g_maps->_forwardMask != DIRMASK_E) {
+ g_maps->clearSpecial();
+ return;
+ }
+ } else {
+ _data[VAL2] = 1;
+ }
+
+ fountain();
+}
+
+void Map23::special12() {
+ send(SoundMessage(14, 22, STRING["maps.map23.avalanche"]));
+ g_maps->_currentState = 209;
+ _walls[g_maps->_mapOffset] = 0xff;
+ _states[g_maps->_mapOffset] = 162;
+
+ g_maps->clearSpecial();
+}
+
+void Map23::special13() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[2] = 4;
+ g_globals->_treasure[3] = 171;
+ g_globals->_treasure[4] = 183;
+ g_globals->_treasure[5] = 191;
+ g_globals->_treasure[6] = 12;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map23::fountain() {
+ send(SoundMessage(
+ STRING["maps.map23.fountain"],
+ []() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+ int attrNum = getRandomNumber(8) - 1;
+ c.getAttribute(attrNum)._current = 30;
+ }
+
+ g_events->send(InfoMessage(16, 2, STRING["maps.map23.cheers"]));
+ }
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map23.h b/engines/mm/mm1/maps/map23.h
index 5e10632957c..d455c723ced 100644
--- a/engines/mm/mm1/maps/map23.h
+++ b/engines/mm/mm1/maps/map23.h
@@ -32,9 +32,32 @@ class Map23 : public Map {
typedef void (Map23:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void fountain();
- const SpecialFn SPECIAL_FN[1] = {
- &Map23::special00
+ const SpecialFn SPECIAL_FN[14] = {
+ &Map23::special00,
+ &Map23::special01,
+ &Map23::special02,
+ &Map23::special03,
+ &Map23::special03,
+ &Map23::special03,
+ &Map23::special03,
+ &Map23::special03,
+ &Map23::special08,
+ &Map23::special09,
+ &Map23::special10,
+ &Map23::special11,
+ &Map23::special12,
+ &Map23::special13
};
public:
Map23() : Map(23, "areac2", 0xA11) {}
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index fb8b6c2b8d2..5abb1564159 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -31,7 +31,7 @@ namespace Maps {
void Map24::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < 14; ++i) {
+ for (uint i = 0; i < 10; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
@@ -45,38 +45,16 @@ void Map24::special() {
}
g_maps->clearSpecial();
- InfoMessage msg(
- 14, 2, STRING["maps.map24.look_out"],
- []() {
- g_globals->_encounters.execute();
- }
- );
- msg._delaySeconds = 2;
- send(msg);
+ g_globals->_encounters.execute();
}
void Map24::special00() {
- send(SoundMessage(
- STRING["maps.map24.passage"],
- []() {
- g_maps->_mapPos = Common::Point(12, 0);
- g_maps->changeMap(0x604, 1);
- }
- ));
}
void Map24::special01() {
- send(SoundMessage(
- STRING["maps.map24.cave"],
- []() {
- g_maps->_mapPos = Common::Point(2, 0);
- g_maps->changeMap(1, 1);
- }
- ));
}
void Map24::special02() {
- g_events->addView("Gypsy");
}
void Map24::special03() {
@@ -88,18 +66,6 @@ void Map24::special08() {
void Map24::special09() {
}
-void Map24::special10() {
-}
-
-void Map24::special11() {
-}
-
-void Map24::special12() {
-}
-
-void Map24::special13() {
-}
-
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map24.h b/engines/mm/mm1/maps/map24.h
index 9c51cd0b601..7333e1a00c8 100644
--- a/engines/mm/mm1/maps/map24.h
+++ b/engines/mm/mm1/maps/map24.h
@@ -37,12 +37,8 @@ private:
void special03();
void special08();
void special09();
- void special10();
- void special11();
- void special12();
- void special13();
- const SpecialFn SPECIAL_FN[14] = {
+ const SpecialFn SPECIAL_FN[10] = {
&Map24::special00,
&Map24::special01,
&Map24::special02,
@@ -52,11 +48,7 @@ private:
&Map24::special03,
&Map24::special03,
&Map24::special08,
- &Map24::special09,
- &Map24::special10,
- &Map24::special11,
- &Map24::special12,
- &Map24::special13
+ &Map24::special09
};
public:
Map24() : Map(24, "areac3", 0x904) {}
Commit: 16b0c85dafd909376a2fa5cf0f0b83db86126dba
https://github.com/scummvm/scummvm/commit/16b0c85dafd909376a2fa5cf0f0b83db86126dba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:24+01:00
Commit Message:
MM: MM1: Added map 24
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/maps/map24.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ca7e9032763..552d04fe991 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1151,3 +1151,13 @@ maps:
5: "ORANGE OOLAK"""
6: "BLACK DRESIDION"""
7: "WHITE DILITHIUM"""
+
+ map24:
+ wyverns: "WYVERNS ATTACK FROM ABOVE!"
+ wyvern_eys: "ONE OF THE WYVERN'S EYES BEGINS TO GLOW!TAKE IT (Y/N)?"
+ roadsign: "ROADSIGN: SORPIGAL N.22, W.2, N.2"
+ kilburn: "THE EXILED LORD KILBURN SPEAKS:\n""TAKE THIS MAP AND EXPLORE THE DESERT.\nREPORT YOUR FINDINGS TO THE OTHER LORDS.\nTHEN THEY WILL UNDERSTAND!"" ACCEPT(Y/N)?"
+ backpacks_full: "*** BACKPACKS FULL!"
+ lair: "A WYVERN'S LAIR, INVESTIGATE (Y/N)?"
+ sign: "PAINTED IN A BLACK AND WHITE PATTERN,\nA SIGN READS: THE FIRST PART IS FEMALE."
+ hermit: "THE HERMIT SAYS: ""TRADE WARES (Y/N)?"""
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index f86d1fa0522..13cfb6be77a 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -35,7 +35,11 @@ enum ItemId {
VELLUM_SCROLL_ID = 231,
RUBY_WHISTLE_ID = 232,
BRONZE_KEY_ID = 237,
- DIAMOND_KEY_ID = 240
+ DIAMOND_KEY_ID = 240,
+ MAP_OF_DESERT_ID = 242,
+ PIRATES_MAP_A_ID = 250,
+ PIRATES_MAP_B_ID = 251,
+ USELESS_ITEM_ID = 255
};
enum EnablementBit {
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index 5abb1564159..75b3732aa33 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -29,6 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 91
+
void Map24::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < 10; ++i) {
@@ -49,21 +51,104 @@ void Map24::special() {
}
void Map24::special00() {
+ send(SoundMessage(STRING["maps.map24.roadsign"]));
}
void Map24::special01() {
+ send(SoundMessage(
+ STRING["maps.map24.kilburn"],
+ []() {
+ Map24 &map = *static_cast<Map24 *>(g_maps->_currentMap);
+ if (!map.addItem(MAP_OF_DESERT_ID))
+ none160();
+ }
+ ));
}
void Map24::special02() {
+ send(SoundMessage(
+ STRING["maps.map24.lair"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(4) + 3;
+
+ enc.clearMonsters();
+ enc.addMonster(6, 8);
+ for (int i = 1; i < monsterCount; ++i)
+ enc.addMonster(14, 7);
+
+ enc._flag = true;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc._levelIndex = 40;
+ enc.execute();
+ }
+ ));
}
void Map24::special03() {
+ g_maps->clearSpecial();
+
+ SoundMessage msg(
+ STRING["maps.map24.wyverns"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(4) + 3;
+ enc.clearMonsters();
+ for (int i = 1; i < monsterCount; ++i)
+ enc.addMonster(14, 7);
+
+ enc._flag = true;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc._levelIndex = 40;
+ enc.execute();
+ }
+ );
+ msg._delaySeconds = 3;
+ send(msg);
}
void Map24::special08() {
+ send(SoundMessage(STRING["maps.map24.sign"]));
}
void Map24::special09() {
+ send(SoundMessage(
+ STRING["maps.map24.hermit"],
+ []() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ c._backpack.clear();
+ for (int j = 0; j < INVENTORY_COUNT; ++j)
+ c._backpack.add(USELESS_ITEM_ID, 0);
+ }
+
+ Character &c = g_globals->_party[0];
+ g_globals->_currCharacter = &c;
+ c._backpack[0]._id = PIRATES_MAP_A_ID;
+ c._backpack[1]._id = PIRATES_MAP_B_ID;
+
+ g_maps->clearSpecial();
+ none160();
+ }
+ ));
+}
+
+bool Map24::addItem(byte itemId) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ g_globals->_currCharacter = &c;
+
+ if (!c._backpack.full()) {
+ c._backpack.add(itemId, 20);
+ return false;
+ }
+ }
+
+ g_events->send(SoundMessage(STRING["maps.map24.backpacks_full"]));
+ Sound::sound(SOUND_3);
+ return true;
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map24.h b/engines/mm/mm1/maps/map24.h
index 7333e1a00c8..b35ad96bc65 100644
--- a/engines/mm/mm1/maps/map24.h
+++ b/engines/mm/mm1/maps/map24.h
@@ -57,6 +57,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Adds an item to the party
+ */
+ static bool addItem(byte itemId);
};
} // namespace Maps
Commit: c6fc9a803d572cd7814fc27d03f25d0f0fda154f
https://github.com/scummvm/scummvm/commit/c6fc9a803d572cd7814fc27d03f25d0f0fda154f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Added map 25
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/maps/map25.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 552d04fe991..a7b770bb73f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1161,3 +1161,14 @@ maps:
lair: "A WYVERN'S LAIR, INVESTIGATE (Y/N)?"
sign: "PAINTED IN A BLACK AND WHITE PATTERN,\nA SIGN READS: THE FIRST PART IS FEMALE."
hermit: "THE HERMIT SAYS: ""TRADE WARES (Y/N)?"""
+
+ map25:
+ slab: "A LARGE SLAB OF CORAL BLOCKS A PASSAGE!\n"
+ key: "YOUR CORAL KEY FITS PERFECTLY\nIN THE LOCK, ENTER (Y/N)?"
+ ship: "AT THE WATERS EDGE ARE THE DECAYING\nREMAINS OF A LARGE SHIP. SEARCH(Y/N)?"
+ natives: "CRAZED NATIVES ATTACK!"
+ volcano: "THE VOLCANO ERUPTS!"
+ pirates: "PIRATES ATTACK!"
+ weeping: "MYSTERIOUS WEEPING ECHOES THROUGHOUT!"
+ jolly_raven: "THE JOLLY RAVEN!"
+ portal: "PORTAL OF POWER, ENTER (Y/N)?"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 8ea176e5d2c..306d33258eb 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -104,7 +104,14 @@ enum CharFlags5 {
};
enum CharFlags7 {
- CHARFLAG7_20 = 0x20
+ CHARFLAG7_1 = 1,
+ CHARFLAG7_2 = 2,
+ CHARFLAG7_4 = 4,
+ CHARFLAG7_8 = 8,
+ CHARFLAG7_10 = 0x10,
+ CHARFLAG7_20 = 0x20,
+ CHARFLAG7_40 = 0x40,
+ CHARFLAG7_80 = 0x80
};
enum CharFlags11 {
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 13cfb6be77a..72cb8787c97 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -34,6 +34,7 @@ namespace MM1 {
enum ItemId {
VELLUM_SCROLL_ID = 231,
RUBY_WHISTLE_ID = 232,
+ CORAL_KEY_ID = 236,
BRONZE_KEY_ID = 237,
DIAMOND_KEY_ID = 240,
MAP_OF_DESERT_ID = 242,
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index e3286035005..3f6e9e92bac 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -30,13 +30,14 @@ namespace MM1 {
namespace Maps {
void Map25::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 3; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[54 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,149 @@ void Map25::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ switch (_states[g_maps->_mapOffset]) {
+ case 0:
+ if (getRandomNumber(100) == 100) {
+ Character &c = g_globals->_party[0];
+ g_globals->_currCharacter = &c;
+ int val = getRandomNumber((c._level >= 12 ? 14 : c._level) + 2);
+ int monsterCount = getRandomNumber((val < 15) ? 13 : 4);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(val, 11);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+
+ } else {
+ switch (getRandomNumber(100)) {
+ case 99:
+ send(SoundMessage(STRING["maps.map25.volcano"]));
+ reduceHP();
+ Sound::sound(SOUND_3);
+ break;
+
+ case 100: {
+ SoundMessage msg(
+ STRING["maps.map25.pirates"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(8) + 4;
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(12, 12);
+
+ enc._levelIndex = 64;
+ enc._flag = true;
+ enc.execute();
+ }
+ );
+ msg._delaySeconds = 3;
+ send(msg);
+ break;
+ }
+
+ default:
+ none160();
+ break;
+ }
+ }
+ break;
+
+ case 0x55:
+ if (g_maps->_mapPos.y < 9) {
+ nativesAttack();
+ } else {
+ if (g_maps->_mapPos.x >= 10) {
+ SoundMessage msg(STRING["maps.map25.weeping"]);
+ if (getRandomNumber(100) >= 99) {
+ msg._delaySeconds = 3;
+ msg._ynCallback = []() {
+ g_globals->_encounters.execute();
+ };
+ }
+
+ send(msg);
+ } else if (getRandomNumber(100) >= 99) {
+ g_globals->_encounters.execute();
+ }
+ }
+ break;
+
+ default:
+ send(SoundMessage(
+ STRING["maps.map25.ship"],
+ []() {
+ g_maps->clearSpecial();
+ if (g_maps->_mapOffset == 216) {
+ g_events->send(SoundMessage(STRING["maps.map25.jolly_raven"]));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_currCharacter = &g_globals->_party[i];
+ g_globals->_currCharacter->_flags[7] |= CHARFLAG7_10;
+ }
+
+ g_globals->_treasure[8] = 20;
+ } else {
+ g_globals->_activeSpells._s.cursed = 10;
+ g_globals->_encounters.execute();
+ }
+ }
+ ));
+ break;
+ }
}
void Map25::special00() {
+ send(SoundMessage(
+ STRING["maps.map25.portal"],
+ []() {
+ g_maps->_mapPos = Common::Point(12, 4);
+ g_maps->changeMap(0x201, 3);
+ }
+ ));
+}
+
+void Map25::special01() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c.hasItem(CORAL_KEY_ID)) {
+ send(InfoMessage(
+ STRING["maps.map25.key"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 5);
+ g_maps->changeMap(0x212, 1);
+ }
+ ));
+ }
+ }
+}
+
+void Map25::special02() {
+ nativesAttack();
+}
+
+void Map25::nativesAttack() {
+ SoundMessage msg(
+ STRING["maps.map25.natives"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(6) + 7;
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(9, 12);
+
+ g_maps->clearSpecial();
+ enc._levelIndex = 64;
+ enc._flag = true;
+ enc.execute();
+ }
+ );
+ msg._delaySeconds = 3;
+ send(msg);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map25.h b/engines/mm/mm1/maps/map25.h
index 881b3a90905..2d44a526a2a 100644
--- a/engines/mm/mm1/maps/map25.h
+++ b/engines/mm/mm1/maps/map25.h
@@ -32,9 +32,14 @@ class Map25 : public Map {
typedef void (Map25:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map25::special00
+ void special01();
+ void special02();
+ void nativesAttack();
+
+ const SpecialFn SPECIAL_FN[3] = {
+ &Map25::special00,
+ &Map25::special01,
+ &Map25::special02
};
public:
Map25() : Map(25, "areac4", 0xF04) {}
Commit: 09c3b7abadd4b1d981526eb4328e48c18c3ef0be
https://github.com/scummvm/scummvm/commit/09c3b7abadd4b1d981526eb4328e48c18c3ef0be
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Added map 26
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map26.cpp
engines/mm/mm1/maps/map26.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index a7b770bb73f..7745dac78f9 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1172,3 +1172,13 @@ maps:
weeping: "MYSTERIOUS WEEPING ECHOES THROUGHOUT!"
jolly_raven: "THE JOLLY RAVEN!"
portal: "PORTAL OF POWER, ENTER (Y/N)?"
+
+ map26:
+ scorpion: "SUDDENLY, A GARGANTUAN SCORPION ATTACKS!"
+ trading_post: "A SMALL TRIBE OF DESERT NOMADS HAVE\nESTABLISHED A TRADING POST HERE.\nTRADE ITEM (Y/N)?"
+ leader_nothing: "YOUR LEADER HAS NOTHING TO TRADE!"
+ kilburn: "KILBURN, C-3 6-14"
+ its_hot: "IT'S HOT... "
+ lost: "YOU'RE LOST!!!"
+ whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
+ sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 72cb8787c97..93252f9121d 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -37,6 +37,7 @@ enum ItemId {
CORAL_KEY_ID = 236,
BRONZE_KEY_ID = 237,
DIAMOND_KEY_ID = 240,
+ CACTUS_NECTAR_ID = 241,
MAP_OF_DESERT_ID = 242,
PIRATES_MAP_A_ID = 250,
PIRATES_MAP_B_ID = 251,
diff --git a/engines/mm/mm1/maps/map26.cpp b/engines/mm/mm1/maps/map26.cpp
index 22bbb5a35a6..94e7167800c 100644
--- a/engines/mm/mm1/maps/map26.cpp
+++ b/engines/mm/mm1/maps/map26.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 247
+
void Map26::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 4; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[55 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,146 @@ void Map26::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ SoundMessage msg;
+ msg._lines.push_back(Line(0, 1, STRING["maps.map26.its_hot"]));
+
+ // Check whether party has the desert map
+ bool hasMap = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasMap; ++i) {
+ hasMap = g_globals->_party[i].hasItem(MAP_OF_DESERT_ID);
+ }
+ if (!hasMap) {
+ msg._lines.push_back(Line(0, 2, STRING["maps.map26.lost"]));
+ lost();
+ }
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ if (c._food) {
+ // Take away food first
+ c._food--;
+
+ } else if (c._endurance) {
+ // Then decrease endurance when the food runs out
+ c._endurance._current--;
+
+ } else {
+ // When endurance reaches, character becomes living impaired
+ c._condition = DEAD | BAD_CONDITION;
+ _data[VAL1]++;
+ }
+ }
+
+ if (_data[VAL1])
+ g_events->findView("GameParty")->redraw();
+
+ switch (getRandomNumber(200)) {
+ case 20:
+ msg._lines.push_back(Line(0, msg._lines.back().y + 1,
+ STRING["maps.map26.whirlwind"]));
+ Sound::sound(SOUND_3);
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(15), getRandomNumber(15));
+
+ send(msg);
+ updateGame();
+ return;
+
+ case 30:
+ msg._lines.push_back(Line(0, msg._lines.back().y + 1,
+ STRING["maps.map26.sandstorm"]));
+ Sound::sound(SOUND_3);
+ reduceHP();
+ break;
+
+ case 199:
+ case 200:
+ g_globals->_encounters.execute();
+ break;
+
+ default:
+ break;
+ }
+
+ send(msg);
}
void Map26::special00() {
+ if (_data[VAL1]) {
+ addFlag();
+
+ } else {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (g_globals->_party[i]._flags[2] & CHARFLAG2_2) {
+ g_maps->clearSpecial();
+ none160();
+ return;
+ }
+ }
+
+ SoundMessage msg(
+ STRING["maps.map26.scorpion"],
+ []() {
+ Map26 &map = *static_cast<Map26 *>(g_maps->_currentMap);
+ Game::Encounter &enc = g_globals->_encounters;
+ map[VAL1]++;
+
+ enc.clearMonsters();
+ enc.addMonster(1, 12);
+ for (int i = 1; i < 14; ++i)
+ enc.addMonster(5, 5);
+
+ enc._levelIndex = 80;
+ enc._flag = true;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc.execute();
+ }
+ );
+ msg._delaySeconds = 4;
+ send(msg);
+ }
+}
+
+void Map26::special01() {
+ _data[VAL1] = 0;
+ none160();
+}
+
+void Map26::special02() {
+ send(SoundMessage(
+ STRING["maps.map26.trading_post"],
+ []() {
+ Character &c = g_globals->_party[0];
+ if (c._backpack.empty()) {
+ g_events->send(SoundMessage(STRING["maps.map26.nothing_to_trade"]));
+ } else {
+ c._backpack[0]._id = CACTUS_NECTAR_ID;
+ c._backpack[0]._charges = 10;
+ }
+ }
+ ));
+}
+
+void Map26::special03() {
+ send(SoundMessage(STRING["maps.map26.kilburn"]));
+}
+
+void Map26::lost() {
+ if (getRandomNumber(2) == 1) {
+ g_maps->turnLeft();
+ } else {
+ g_maps->turnRight();
+ }
+}
+
+void Map26::addFlag() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i)
+ g_globals->_party[i]._flags[2] |= CHARFLAG2_2;
+
+ g_maps->clearSpecial();
+ none160();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map26.h b/engines/mm/mm1/maps/map26.h
index f1691a8de51..ef28439139c 100644
--- a/engines/mm/mm1/maps/map26.h
+++ b/engines/mm/mm1/maps/map26.h
@@ -32,9 +32,17 @@ class Map26 : public Map {
typedef void (Map26:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map26::special00
+ void special01();
+ void special02();
+ void special03();
+ void lost();
+ void addFlag();
+
+ const SpecialFn SPECIAL_FN[4] = {
+ &Map26::special00,
+ &Map26::special01,
+ &Map26::special02,
+ &Map26::special03
};
public:
Map26() : Map(26, "aread1", 0x505) {}
Commit: 9e705307ad69eef2396c79c7b3787ee7e6727ae9
https://github.com/scummvm/scummvm/commit/9e705307ad69eef2396c79c7b3787ee7e6727ae9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Added map 28
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map26.cpp
engines/mm/mm1/maps/map27.cpp
engines/mm/mm1/maps/map27.h
engines/mm/mm1/maps/map28.cpp
engines/mm/mm1/maps/map28.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 7745dac78f9..c990872fa5b 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1182,3 +1182,31 @@ maps:
lost: "YOU'RE LOST!!!"
whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
+
+ map27:
+ pool: "THE POOL OF WISDOM GRANTS THOSE WHO ARE\nWORTHY +4 PERSONALITY."
+ retreat: "CLERICAL RETREAT"
+ clerics: "WE ARE THE CLERICS OF THE "
+ cured: "YOUR PARTY IS CURED!"
+ alignment: "YOUR ALIGNMENT IS RESTORED!"
+ curses: "ALL CURSES ARE REMOVED!"
+ sign: "THE CLERICS OF THE S. SHALL DEEM YOU\nWORTHY, IF YOU CAN FIND THEM!"
+ its_hot: "IT'S HOT... "
+ lost: "YOU'RE LOST!!!"
+
+ map28:
+ cave: "A CAVE, ENTER (Y/N)?"
+ tree: "CLIMB TREE (Y/N)?"
+ arenko: "I AM ARENKO GUIRE AND THIS IS MY GROVE.\nCLIMB ALL THE TREES, WITHOUT LEAVING\nTHE AREA, AND RETURN."
+ well_done: "WELL DONE! WHAT IS YOUR PLEASURE?\nA) GOLD B) GEMS C) ITEM"
+ food: "+5 FOOD"
+ thorns: "POISON THORNS"
+ you_fell: "YOU FELL"
+ lightning: "LIGHTNING"
+ sap: "INFECTIOUS SAP"
+ flash: "FLASH"
+ poof: "POOF!"
+ nothing: "NOTHING HERE."
+ cursed: "CURSED"
+ keep_climbing: "KEEP CLIMBING."
+ sign: "ROADSIGN: ALGARY S.9"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 306d33258eb..2e35a8d35df 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -116,7 +116,7 @@ enum CharFlags7 {
enum CharFlags11 {
CHARFLAG11_GOT_ENDURANCE = 1,
- CHARFLAG11_2 = 2,
+ CHARFLAG11_PERSONALITY = 2,
CHARFLAG11_4 = 4,
CHARFLAG11_GOT_MIGHT = 8,
CHARFLAG11_GOT_ACCURACY = 0x10,
diff --git a/engines/mm/mm1/maps/map26.cpp b/engines/mm/mm1/maps/map26.cpp
index 94e7167800c..48fbbdbf83b 100644
--- a/engines/mm/mm1/maps/map26.cpp
+++ b/engines/mm/mm1/maps/map26.cpp
@@ -59,6 +59,7 @@ void Map26::special() {
lost();
}
+ _data[VAL1] = 0;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
index fe3273b7e0d..ec93cc8591a 100644
--- a/engines/mm/mm1/maps/map27.cpp
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 66
+
void Map27::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 6; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[57 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,137 @@ void Map27::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ SoundMessage msg;
+ msg._lines.push_back(Line(0, 1, STRING["maps.map27.its_hot"]));
+
+ // Check whether party has the desert map
+ bool hasMap = false;
+ for (uint i = 0; i < g_globals->_party.size() && !hasMap; ++i) {
+ hasMap = g_globals->_party[i].hasItem(MAP_OF_DESERT_ID);
+ }
+ if (!hasMap) {
+ msg._lines.push_back(Line(0, 2, STRING["maps.map27.lost"]));
+ lost();
+ }
+
+ _data[VAL1] = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ if (c._food) {
+ // Take away food first
+ c._food--;
+
+ } else if (c._endurance) {
+ // Then decrease endurance when the food runs out
+ c._endurance._current--;
+
+ } else {
+ // When endurance reaches, character becomes living impaired
+ c._condition = DEAD | BAD_CONDITION;
+ _data[VAL1]++;
+ }
+ }
+
+ if (_data[VAL1])
+ g_events->findView("GameParty")->redraw();
+
+ if (getRandomNumber(100) == 100) {
+ msg._keyCallback = [](const Common::KeyState &ks) {
+ g_globals->_encounters.execute();
+ };
+ }
+
+ send(msg);
}
void Map27::special00() {
+ send(SoundMessage(STRING["maps.map27.pool"]));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._flags[11] & CHARFLAG11_PERSONALITY)) {
+ c._flags[11] |= CHARFLAG11_PERSONALITY;
+ if (c._personality._base < 30) {
+ c._personality._current = c._personality._base += 4;
+ }
+ }
+ }
+}
+
+void Map27::special01() {
+ send(SoundMessage(STRING["maps.map27.retreat"]));
+}
+
+void Map27::special02() {
+ send(SoundMessage(
+ 0, 1, clerics('N'),
+ 0, 2, STRING["maps.map27.cured"]
+ ));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c._condition != ERADICATED) {
+ c._condition = 0;
+ c._hpBase = c._hpMax = c._hp;
+ }
+ }
+
+ g_maps->clearSpecial();
+}
+
+void Map27::special03() {
+ send(SoundMessage(
+ 0, 1, clerics('E'),
+ 0, 2, STRING["maps.map27.alignment"]
+ ));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._alignment = c._alignmentInitial;
+ }
+}
+
+void Map27::special04() {
+ send(SoundMessage(
+ 0, 1, clerics('W'),
+ 0, 2, STRING["maps.map27.curses"]
+ ));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ for (int invNum = 0; invNum < 2; ++invNum) {
+ Inventory &inv = (invNum == 0) ? c._equipped : c._backpack;
+
+ for (int itemNum = (int)inv.size() - 1; itemNum >= 0; --itemNum) {
+ Item *item = g_globals->_items.getItem(c._equipped[itemNum]._id);
+ if (item->_equipMode == EQUIP_CURSED)
+ inv.removeAt(itemNum);
+ }
+ }
+ }
+
+ g_globals->_activeSpells._s.cursed = 0;
+
+}
+
+void Map27::special05() {
+ send(SoundMessage(STRING["maps.map27.sign"]));
+}
+
+void Map27::lost() {
+ if (getRandomNumber(2) == 1) {
+ g_maps->turnLeft();
+ } else {
+ g_maps->turnRight();
+ }
+}
+
+Common::String Map27::clerics(char name) {
+ return Common::String::format("%s %c.",
+ STRING["maps.map27.clerics"], name);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map27.h b/engines/mm/mm1/maps/map27.h
index 57a8921c999..82856e7f92c 100644
--- a/engines/mm/mm1/maps/map27.h
+++ b/engines/mm/mm1/maps/map27.h
@@ -32,9 +32,21 @@ class Map27 : public Map {
typedef void (Map27:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void lost();
+ Common::String clerics(char name);
- const SpecialFn SPECIAL_FN[1] = {
- &Map27::special00
+ const SpecialFn SPECIAL_FN[6] = {
+ &Map27::special00,
+ &Map27::special01,
+ &Map27::special02,
+ &Map27::special03,
+ &Map27::special04,
+ &Map27::special05
};
public:
Map27() : Map(27, "aread2", 0xB05) {}
diff --git a/engines/mm/mm1/maps/map28.cpp b/engines/mm/mm1/maps/map28.cpp
index 70494677a50..8b4e91f2840 100644
--- a/engines/mm/mm1/maps/map28.cpp
+++ b/engines/mm/mm1/maps/map28.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/maps/map28.h"
#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/data/locations.h"
#include "mm/mm1/events.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
@@ -29,14 +30,16 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 63
+#define VAL2 64
+
void Map28::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 3; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[54 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +47,159 @@ void Map28::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (g_maps->_mapPos.x >= 7) {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+
+ } else {
+ send(SoundMessage(
+ STRING["maps.map28.tree"],
+ []() {
+ Map28 &map = *static_cast<Map28 *>(g_maps->_currentMap);
+
+ if (!map[VAL2]) {
+ g_events->send(SoundMessage(STRING["maps.map28.nothing"]));
+
+ } else {
+ g_maps->clearSpecial();
+ map[VAL1]++;
+
+ int val = getRandomNumber(10);
+ switch (val) {
+ case 1:
+ g_events->send(SoundMessage(STRING["maps.map28.nothing"]));
+ break;
+
+ case 2:
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._food = MIN((int)c._food + 5, MAX_FOOD);
+ }
+ g_events->send(SoundMessage(STRING["maps.map28.food"]));
+ break;
+
+ case 3:
+ map.setCondition(POISONED);
+ map.reduceHpBase();
+ g_events->send(SoundMessage(STRING["maps.map28.thorns"]));
+ break;
+
+ case 4:
+ if (g_globals->_activeSpells._s.levitate) {
+ g_events->send(SoundMessage(STRING["maps.map28.nothing"]));
+ } else {
+ map.reduceHpBase();
+ map.reduceHpBase();
+ g_events->send(SoundMessage(STRING["maps.map28.you_fell"]));
+ }
+ break;
+
+ case 5:
+ g_events->send(SoundMessage(STRING["maps.map28.lightning"]));
+ break;
+
+ case 6:
+ map.setCondition(DISEASED);
+ map.reduceHpBase();
+ g_events->send(SoundMessage(STRING["maps.map28.lightning"]));
+ break;
+
+ case 7:
+ if (!g_globals->_activeSpells._s.psychic_protection) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._sp._current = 0;
+ }
+ }
+
+ g_events->send(SoundMessage(STRING["maps.map28.flash"]));
+ break;
+
+ case 8:
+ g_events->send(SoundMessage(STRING["maps.map28.poof"]));
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(15), getRandomNumber(15));
+ updateGame();
+ break;
+
+ default:
+ g_globals->_activeSpells._s.cursed = val;
+ break;
+ }
+ }
+ }
+ ));
+ }
}
void Map28::special00() {
+ if (!_data[VAL1]) {
+ send(SoundMessage(STRING["maps.map28.arenko"]));
+ _data[VAL2] = 1;
+ } else if (_data[VAL1] < 19) {
+ send(SoundMessage(STRING["maps.map28.keep_climbing"]));
+ } else {
+ send(SoundMessage(
+ STRING["maps.map28.well_done"],
+ [](const Common::KeyState &ks) {
+ switch (ks.keycode) {
+ case Common::KEYCODE_a:
+ g_events->close();
+ g_globals->_treasure[7] = getRandomNumber(8) + 8;
+ g_maps->clearSpecial();
+ g_events->addAction(KEYBIND_SEARCH);
+ break;
+
+ case Common::KEYCODE_b:
+ g_events->close();
+ g_globals->_treasure[8] = getRandomNumber(50) + 200;
+ g_maps->clearSpecial();
+ g_events->addAction(KEYBIND_SEARCH);
+ break;
+
+ case Common::KEYCODE_c:
+ g_events->close();
+ g_globals->_treasure[5] = getRandomNumber(22) + 196;
+ g_maps->clearSpecial();
+ g_events->addAction(KEYBIND_SEARCH);
+ break;
+
+ default:
+ break;
+ }
+ }
+ ));
+ }
+}
+
+void Map28::special01() {
+ send(SoundMessage(
+ STRING["maps.map28.cave"],
+ []() {
+ g_maps->_mapPos = Common::Point(8, 8);
+ g_maps->changeMap(0x601, 1);
+ }
+ ));
+}
+
+void Map28::special02() {
+ send(SoundMessage(STRING["maps.map28.sign"]));
+}
+
+void Map28::setCondition(byte condition) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (getRandomNumber(3) == 2 && !(c._condition & BAD_CONDITION))
+ c._condition = condition;
+ }
+}
+
+void Map28::reduceHpBase() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._hpBase /= 2;
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map28.h b/engines/mm/mm1/maps/map28.h
index 2eacdc11c97..7697b4f38b2 100644
--- a/engines/mm/mm1/maps/map28.h
+++ b/engines/mm/mm1/maps/map28.h
@@ -32,9 +32,15 @@ class Map28 : public Map {
typedef void (Map28:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map28::special00
+ void special01();
+ void special02();
+ void setCondition(byte condition);
+ void reduceHpBase();
+
+ const SpecialFn SPECIAL_FN[3] = {
+ &Map28::special00,
+ &Map28::special01,
+ &Map28::special02
};
public:
Map28() : Map(28, "aread3", 0x106) {}
Commit: d0fccd35def3491f0e94a07a3fccf0a0a3cfb37a
https://github.com/scummvm/scummvm/commit/d0fccd35def3491f0e94a07a3fccf0a0a3cfb37a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Added map 29
Changed paths:
A engines/mm/mm1/views/maps/chess.cpp
A engines/mm/mm1/views/maps/chess.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map26.cpp
engines/mm/mm1/maps/map27.cpp
engines/mm/mm1/maps/map29.cpp
engines/mm/mm1/maps/map29.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c990872fa5b..dab9cf7ddde 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1210,3 +1210,11 @@ maps:
cursed: "CURSED"
keep_climbing: "KEEP CLIMBING."
sign: "ROADSIGN: ALGARY S.9"
+
+ map29:
+ algary: "ALGARY, ENTER (Y/N)?"
+ attack: "PAUL PEAD AND HIS MEN ATTACK!"
+ beast: "A HUGE WINGED BEAST EXCLAIMS,\n""THIS SWAMP IS QUITE DANGEROUS. FLY YOU\nTO SAFETY (Y/N)?"""
+ begone: "OG SAYS, ""BEGONE!"""
+ chess: "PAINTED ON THESE GROUNDS IS A BLACK &\nWHITE CHECKERED MOTIF COVERED WITH\nIDOLS SIMILAR TO THE ONES YOU CARRY.\nA LARGE BEING APPROACHES...\nOG SPEAKS, ""QUEEN TO QUEENS LEVEL 3""\n\nRESPONSE: "
+ restored_sight: "YOU HAVE RESTORED MY SIGHT! (+25000 EXP)\nI SEE AN IMPORTANT PRISONER IN A CASTLE\nON MT. DOOM! HE HAS YOUR SIGHT.\n\nOG CURSES AS THE IDOLS VANISH!"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 93252f9121d..857fd980f29 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -39,6 +39,8 @@ enum ItemId {
DIAMOND_KEY_ID = 240,
CACTUS_NECTAR_ID = 241,
MAP_OF_DESERT_ID = 242,
+ B_QUEEN_IDOL_ID = 248,
+ W_QUEEN_IDOL_ID = 249,
PIRATES_MAP_A_ID = 250,
PIRATES_MAP_B_ID = 251,
USELESS_ITEM_ID = 255
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 5195f0510e1..b09a797e55e 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -91,5 +91,16 @@ void Party::combatDone() {
}
}
+bool Party::hasItem(byte itemId) const {
+ for (uint i = 0; i < size(); ++i) {
+ const Character &c = (*this)[i];
+ if (c._equipped.indexOf(itemId) != -1 ||
+ c._backpack.indexOf(itemId) != -1)
+ return true;
+ }
+
+ return false;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index ad6445cf986..ee7517a0e35 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -65,6 +65,11 @@ struct Party : public Common::Array<Character> {
* Called to update the party after combat is done
*/
void combatDone();
+
+ /**
+ * Returns true if any of the party has an item
+ */
+ bool hasItem(byte itemId) const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 27bde73c4f7..91d7599e0d2 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -122,11 +122,6 @@ protected:
*/
static void none160() {}
- /**
- * Updates the game display
- */
- static void updateGame();
-
public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
@@ -188,6 +183,10 @@ public:
return g_events->send(name, msg);
}
+ /**
+ * Updates the game display
+ */
+ static void updateGame();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map26.cpp b/engines/mm/mm1/maps/map26.cpp
index 48fbbdbf83b..3eb78ba210a 100644
--- a/engines/mm/mm1/maps/map26.cpp
+++ b/engines/mm/mm1/maps/map26.cpp
@@ -50,10 +50,7 @@ void Map26::special() {
msg._lines.push_back(Line(0, 1, STRING["maps.map26.its_hot"]));
// Check whether party has the desert map
- bool hasMap = false;
- for (uint i = 0; i < g_globals->_party.size() && !hasMap; ++i) {
- hasMap = g_globals->_party[i].hasItem(MAP_OF_DESERT_ID);
- }
+ bool hasMap = g_globals->_party.hasItem(MAP_OF_DESERT_ID);
if (!hasMap) {
msg._lines.push_back(Line(0, 2, STRING["maps.map26.lost"]));
lost();
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
index ec93cc8591a..84e1e0dece3 100644
--- a/engines/mm/mm1/maps/map27.cpp
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -50,10 +50,7 @@ void Map27::special() {
msg._lines.push_back(Line(0, 1, STRING["maps.map27.its_hot"]));
// Check whether party has the desert map
- bool hasMap = false;
- for (uint i = 0; i < g_globals->_party.size() && !hasMap; ++i) {
- hasMap = g_globals->_party[i].hasItem(MAP_OF_DESERT_ID);
- }
+ bool hasMap = g_globals->_party.hasItem(MAP_OF_DESERT_ID);
if (!hasMap) {
msg._lines.push_back(Line(0, 2, STRING["maps.map27.lost"]));
lost();
@@ -175,7 +172,7 @@ void Map27::lost() {
Common::String Map27::clerics(char name) {
return Common::String::format("%s %c.",
- STRING["maps.map27.clerics"], name);
+ STRING["maps.map27.clerics"].c_str(), name);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
index 19af3ca66eb..17620247638 100644
--- a/engines/mm/mm1/maps/map29.cpp
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -29,14 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 110
+
void Map29::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 4; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[75 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +47,129 @@ void Map29::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ switch (_states[g_maps->_mapOffset]) {
+ case 0:
+ if (getRandomNumber(50) == 50) {
+ int id1 = getRandomNumber(16);
+ int monsterCount = getRandomNumber(id1 < 15 ? 13 : 4);
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, 11);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+
+ } else {
+ none160();
+ }
+ break;
+
+ case 0xaa:
+ if (g_maps->_forwardMask == DIRMASK_W)
+ checkPartyDead();
+ else
+ // TODO: This key doesn't seem to be used by game
+ g_events->addKeypress((Common::KeyCode)149);
+ break;
+
+ default:
+ g_maps->clearSpecial();
+ enc.execute();
+ break;
+ }
}
void Map29::special00() {
+ send(SoundMessage(
+ STRING["maps.map29.algary"],
+ []() {
+ g_maps->_mapPos = Common::Point(8, 15);
+ g_maps->changeMap(0x203, 1);
+ }
+ ));
+}
+
+void Map29::special01() {
+ if (_data[VAL1]) {
+ g_maps->clearSpecial();
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[2] |= CHARFLAG2_4;
+ }
+ } else {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c._flags[2] & CHARFLAG2_4)
+ return;
+ }
+
+ send(SoundMessage(
+ STRING["maps.map29.beast"],
+ [](const Common::KeyState &ks) {
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+ g_maps->_mapPos = Common::Point(12, 12);
+ updateGame();
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ Game::Encounter &enc = g_globals->_encounters;
+ Map29 &map = *static_cast<Map29 *>(g_maps->_currentMap);
+ g_events->close();
+ map[VAL1]++;
+
+ enc.clearMonsters();
+ enc.addMonster(3, 12);
+ for (int i = 1; i < 13; ++i)
+ enc.addMonster(3, 5);
+
+ enc._flag = true;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
+ }
+ ));
+ }
+}
+
+void Map29::special02() {
+ if (!g_globals->_party.hasItem(B_QUEEN_IDOL_ID) ||
+ !g_globals->_party.hasItem(W_QUEEN_IDOL_ID)) {
+ send(SoundMessage(STRING["maps.map29.begone"]));
+ } else {
+ g_events->addView("Chess");
+ }
+}
+
+void Map29::special03() {
+ SoundMessage msg(
+ STRING["maps.map29.attack"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(5) + 6;
+ g_maps->clearSpecial();
+
+ enc.clearMonsters();
+ enc.addMonster(11, 12);
+ for (int i = 1; i < monsterCount; ++i)
+ enc.addMonster(1, 7);
+
+ enc._flag = true;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
+ );
+ msg._delaySeconds = 4;
+ send(msg);
+}
+
+void Map29::begone() {
+ send(SoundMessage(STRING["maps.map29.begone"]));
+ g_maps->_mapPos.y = 7;
+ updateGame();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map29.h b/engines/mm/mm1/maps/map29.h
index e0a7e94894c..6e46ef5a3ec 100644
--- a/engines/mm/mm1/maps/map29.h
+++ b/engines/mm/mm1/maps/map29.h
@@ -32,9 +32,15 @@ class Map29 : public Map {
typedef void (Map29:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map29::special00
+ void special01();
+ void special02();
+ void special03();
+
+ const SpecialFn SPECIAL_FN[4] = {
+ &Map29::special00,
+ &Map29::special01,
+ &Map29::special02,
+ &Map29::special03
};
public:
Map29() : Map(29, "aread4", 0x801) {}
@@ -43,6 +49,8 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ void begone();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 3cdf73f2cd5..d6523a10e0e 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -44,6 +44,7 @@
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
#include "mm/mm1/views/maps/arrested.h"
+#include "mm/mm1/views/maps/chess.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/trivia.h"
@@ -85,6 +86,7 @@ private:
Views::Locations::Training _training;
Views::Maps::Arrested _arrested;
+ Views::Maps::Chess _chess;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Resistances _resistances;
Views::Maps::Trivia _trivia;
diff --git a/engines/mm/mm1/views/maps/chess.cpp b/engines/mm/mm1/views/maps/chess.cpp
new file mode 100644
index 00000000000..e2ea109f845
--- /dev/null
+++ b/engines/mm/mm1/views/maps/chess.cpp
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/chess.h"
+#include "mm/mm1/maps/map29.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define ANSWER_OFFSET 67
+
+Chess::Chess() :
+ AnswerEntry("Chess", Common::Point(10, 7), 23) {
+ _bounds = getLineBounds(17, 24);
+}
+
+bool Chess::msgFocus(const FocusMessage &msg) {
+ Sound::sound(SOUND_3);
+ return AnswerEntry::msgFocus(msg);
+}
+
+void Chess::draw() {
+ clearSurface();
+ writeString(0, 0, STRING["maps.map29.chess"]);
+}
+
+void Chess::answerEntered() {
+ MM1::Maps::Map29 &map = *static_cast<MM1::Maps::Map29 *>(g_maps->_currentMap);
+ Common::String properAnswer;
+
+ for (int i = 0; i < 22; ++i)
+ properAnswer += map[ANSWER_OFFSET + i] + 48;
+
+ if (_answer == properAnswer) {
+ InfoMessage msg(
+ 16, 2, STRING["maps.map19.correct"],
+ []() {
+ MM1::Maps::Map29 &map = *static_cast<MM1::Maps::Map29 *>(g_maps->_currentMap);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._exp += 25000;
+ }
+
+ g_maps->_mapPos.y = 7;
+ map.updateGame();
+ }
+ );
+
+ msg._delaySeconds = 2;
+ send(msg);
+ Sound::sound(SOUND_3);
+ Sound::sound(SOUND_3);
+
+ } else {
+ map.begone();
+ }
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/chess.h b/engines/mm/mm1/views/maps/chess.h
new file mode 100644
index 00000000000..7d4702a2f06
--- /dev/null
+++ b/engines/mm/mm1/views/maps/chess.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_CHESS_H
+#define MM1_VIEWS_MAPS_CHESS_H
+
+#include "mm/mm1/views/maps/answer_entry.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Chess : public AnswerEntry {
+protected:
+ void answerEntered() override;
+
+public:
+ Chess();
+ virtual ~Chess() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b12703dca5a..388703f9028 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -53,6 +53,7 @@ MODULE_OBJS := \
mm1/views/maps/access_code.o \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
+ mm1/views/maps/chess.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
mm1/views/maps/resistances.o \
Commit: dbdd193ef92a2f5228f93bd6a9ad4cc1e7ede16a
https://github.com/scummvm/scummvm/commit/dbdd193ef92a2f5228f93bd6a9ad4cc1e7ede16a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Added map 30
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/map30.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index dab9cf7ddde..1ab7fb6cace 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -819,6 +819,10 @@ maps:
stairs_up: "STAIRS GOING UP! TAKE THEM (Y/N)?"
stairs_down: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
+ desert:
+ its_hot: "IT'S HOT... "
+ youre_lost: "YOU'RE LOST!!!"
+
map00:
blacksmith: """B AND B BLACKSMITHING"""
inn: """THE INN OF SORPIGAL"""
@@ -1218,3 +1222,24 @@ maps:
begone: "OG SAYS, ""BEGONE!"""
chess: "PAINTED ON THESE GROUNDS IS A BLACK &\nWHITE CHECKERED MOTIF COVERED WITH\nIDOLS SIMILAR TO THE ONES YOU CARRY.\nA LARGE BEING APPROACHES...\nOG SPEAKS, ""QUEEN TO QUEENS LEVEL 3""\n\nRESPONSE: "
restored_sight: "YOU HAVE RESTORED MY SIGHT! (+25000 EXP)\nI SEE AN IMPORTANT PRISONER IN A CASTLE\nON MT. DOOM! HE HAS YOUR SIGHT.\n\nOG CURSES AS THE IDOLS VANISH!"
+
+ map30:
+ passage: "PASSAGE TO DUSK, ENTER (Y/N)?"
+ ruins: "RUINS OF CASTLE DRAGADUNE, ENTER (Y/N)?"
+ its_hot: "IT'S HOT... "
+ youre_lost: "YOU'RE LOST!!!"
+ whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
+ sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
+ hourglass: "AT THE CENTER OF THE LAND THAT TIME\nFORGOT STANDS AN HOURGLASS,TURN IT(Y/N)?"
+ unworthy: "NOT WORTHY!"
+ worthy: "YOUR ACTIONS REFLECT YOUR VIEWS %d OF 6\n+"
+ giant: "STATUE OF A GIANT HOLDING THE SCALE OF\nJUDGEMENT. WHO WILL CLIMB ON (1-6)?"
+ experience: "EXPERIENCE"
+ attributes:
+ 0: "INTELLECT"
+ 1: "MIGHT"
+ 2: "PERSONALITY"
+ 3: "ENDURANCE"
+ 4: "SPEED"
+ 5: "ACCURACY"
+ 6: "LUCK"
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index 5a6ebb6ccbc..4d45329310d 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -29,14 +29,20 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 137
+
+static const byte MONSTER_ID1[8] = { 2, 3, 8, 10, 14, 16, 17, 7 };
+static const byte MONSTER_ID2[8] = { 5, 6, 3, 8, 10, 12, 12, 12 };
+
void Map30::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 4; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[65 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +50,135 @@ void Map30::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (_states[g_maps->_mapOffset] != 0xff) {
+ g_maps->clearSpecial();
+ int monsterCount = getRandomNumber(8) + 6;
+ int idx = getRandomNumber(8) - 1;
+ byte id1 = MONSTER_ID1[idx];
+ byte id2 = MONSTER_ID2[idx];
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, id2);
+
+ enc._flag = true;
+ enc._levelIndex = 96;
+ enc.execute();
+ return;
+ }
+
+ SoundMessage msg;
+ msg._lines.push_back(Line(0, 1, STRING["maps.map30.its_hot"]));
+
+ // Check whether party has the desert map
+ bool hasMap = g_globals->_party.hasItem(MAP_OF_DESERT_ID);
+ if (!hasMap) {
+ msg._lines.push_back(Line(0, 2, STRING["maps.map30.lost"]));
+ lost();
+ }
+
+ _data[VAL1] = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ if (c._food) {
+ // Take away food first
+ c._food--;
+
+ } else if (c._endurance) {
+ // Then decrease endurance when the food runs out
+ c._endurance._current--;
+
+ } else {
+ // When endurance reaches, character becomes living impaired
+ c._condition = DEAD | BAD_CONDITION;
+ _data[VAL1]++;
+ }
+ }
+
+ if (_data[VAL1])
+ g_events->findView("GameParty")->redraw();
+
+ switch (getRandomNumber(200)) {
+ case 20:
+ msg._lines.push_back(Line(0, msg._lines.back().y + 1,
+ STRING["maps.map30.whirlwind"]));
+ Sound::sound(SOUND_3);
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(15), getRandomNumber(15));
+
+ send(msg);
+ updateGame();
+ return;
+
+ case 30:
+ msg._lines.push_back(Line(0, msg._lines.back().y + 1,
+ STRING["maps.map30.sandstorm"]));
+ Sound::sound(SOUND_3);
+ reduceHP();
+ break;
+
+ case 199:
+ case 200:
+ g_globals->_encounters.execute();
+ break;
+
+ default:
+ break;
+ }
+
+ send(msg);
}
void Map30::special00() {
+ send(SoundMessage(
+ STRING["maps.map30.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(15, 7);
+ g_maps->changeMap(0x802, 1);
+ }
+ ));
+}
+
+void Map30::special01() {
+ send(SoundMessage(
+ STRING["maps.map30.ruins"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 15);
+ g_maps->changeMap(0x107, 3);
+ }
+ ));
+}
+
+void Map30::special02() {
+ g_events->addView("Giant");
+}
+
+void Map30::special03() {
+ send(SoundMessage(
+ STRING["maps.map30.hourglass"],
+ []() {
+ g_maps->clearSpecial();
+ Sound::sound(SOUND_3);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._age._current = c._age._base =
+ MAX((int)c._age._base - 20, 18);
+ }
+
+ none160();
+ }
+ ));
+}
+
+void Map30::lost() {
+ if (getRandomNumber(2) == 1) {
+ g_maps->turnLeft();
+ } else {
+ g_maps->turnRight();
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map30.h b/engines/mm/mm1/maps/map30.h
index daa9637801e..2d6ab4a2a51 100644
--- a/engines/mm/mm1/maps/map30.h
+++ b/engines/mm/mm1/maps/map30.h
@@ -32,9 +32,16 @@ class Map30 : public Map {
typedef void (Map30:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map30::special00
+ void special01();
+ void special02();
+ void special03();
+ void lost();
+
+ const SpecialFn SPECIAL_FN[4] = {
+ &Map30::special00,
+ &Map30::special01,
+ &Map30::special02,
+ &Map30::special03
};
public:
Map30() : Map(30, "areae1", 0x112) {}
Commit: 189b0e7ec1d4a0e96705b737e31bce4e5df1c2c9
https://github.com/scummvm/scummvm/commit/189b0e7ec1d4a0e96705b737e31bce4e5df1c2c9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Added map 31
Changed paths:
A engines/mm/mm1/maps/map_desert.cpp
A engines/mm/mm1/maps/map_desert.h
A engines/mm/mm1/views/maps/alien.cpp
A engines/mm/mm1/views/maps/alien.h
A engines/mm/mm1/views/maps/giant.cpp
A engines/mm/mm1/views/maps/giant.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/events.h
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map27.cpp
engines/mm/mm1/maps/map31.cpp
engines/mm/mm1/maps/map31.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 1ab7fb6cace..2e952f3fee2 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1243,3 +1243,10 @@ maps:
4: "SPEED"
5: "ACCURACY"
6: "LUCK"
+
+ map31:
+ device: "STRANGE ALIEN DEVICE GRANTS THOSE WHO\nARE WORTHY +4 INTELLECT!"
+ alien: "SCATTERED REMAINS OF A METALLIC CRAFT!\nAN ALIEN GRUNTS, ""EEP OP OOP!""\nREACTION: A)HOSTILE B)NEUTRAL C)FRIENDLY"
+ flash: "A BRIGHT FLASH!"
+ varnlings: """VARNLINGS TAKE HEED! OUR PRISONER HAS\nESCAPED AND MAY BE DISGUISED AS A NOBLE.\nFIND HIS COUNTERPART TO EXPOSE HIM!"""
+ poof: "POOF!"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 2e35a8d35df..09be5b5042d 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -75,7 +75,14 @@ enum CharFlags0 {
};
enum CharFlags1 {
- CHARFLAG1_1 = 1
+ CHARFLAG1_1 = 1,
+ CHARFLAG1_2 = 2,
+ CHARFLAG1_4 = 4,
+ CHARFLAG1_8 = 8,
+ CHARFLAG1_10 = 0x10,
+ CHARFLAG1_20 = 0x20,
+ CHARFLAG1_40 = 0x40,
+ CHARFLAG1_WORTHY = 0x80
};
enum CharFlags2 {
@@ -117,7 +124,7 @@ enum CharFlags7 {
enum CharFlags11 {
CHARFLAG11_GOT_ENDURANCE = 1,
CHARFLAG11_PERSONALITY = 2,
- CHARFLAG11_4 = 4,
+ CHARFLAG11_GOT_INTELLIGENCE = 4,
CHARFLAG11_GOT_MIGHT = 8,
CHARFLAG11_GOT_ACCURACY = 0x10,
CHARFLAG11_GOT_SPEED = 0x20
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index cd09a8fcc34..85ba92f3002 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -98,6 +98,13 @@ protected:
return _timeoutCtr != 0;
}
+ /**
+ * Cancels any active delay
+ */
+ void cancelDelay() {
+ _timeoutCtr = 0;
+ }
+
/**
* Called when an active timeout countdown expired
*/
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index 92ea8d90d4a..91843696bba 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -97,7 +97,8 @@ void Map12::special01() {
for (i = 0; i < (int)g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
if (c._intelligence._base < 25) {
- c._intelligence._current = c._intelligence._base += 2;
+ c._intelligence._current = c._intelligence._base =
+ c._intelligence._base + 2;
}
c._gems = MIN((int)c._gems + 20, 0xffff);
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
index 84e1e0dece3..0198b821892 100644
--- a/engines/mm/mm1/maps/map27.cpp
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -95,7 +95,8 @@ void Map27::special00() {
if (!(c._flags[11] & CHARFLAG11_PERSONALITY)) {
c._flags[11] |= CHARFLAG11_PERSONALITY;
if (c._personality._base < 30) {
- c._personality._current = c._personality._base += 4;
+ c._personality._current = c._personality._base =
+ c._personality._base + 4;
}
}
}
diff --git a/engines/mm/mm1/maps/map31.cpp b/engines/mm/mm1/maps/map31.cpp
index 3620f439b50..0412da83f85 100644
--- a/engines/mm/mm1/maps/map31.cpp
+++ b/engines/mm/mm1/maps/map31.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 79
+
void Map31::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 7; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[58 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,94 @@ void Map31::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+
+ if (_states[g_maps->_mapOffset] != 0xff) {
+ if (getRandomNumber(100) < 25) {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ } else {
+ send(SoundMessage(STRING["maps.map31.poof"]));
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(15), getRandomNumber(15));
+ updateGame();
+ }
+
+ return;
+ }
+
+ desert();
}
void Map31::special00() {
+ send(SoundMessage(STRING["maps.map31.device"]));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ if (!(c._flags[11] & CHARFLAG11_GOT_INTELLIGENCE)) {
+ c._flags[11] |= CHARFLAG11_GOT_INTELLIGENCE;
+ c._intelligence._current = c._intelligence._base =
+ MIN(c._intelligence._base + 4, 30);
+ }
+ }
+}
+
+void Map31::special01() {
+ g_events->addView("Alien");
+}
+
+void Map31::special02() {
+ if (_data[VAL1]) {
+ none160();
+ } else {
+ encounter();
+ }
+}
+
+void Map31::special06() {
+ if (_data[VAL1]) {
+ g_globals->_treasure[5] = 243;
+ g_events->addAction(KEYBIND_SEARCH);
+ } else {
+ none160();
+ }
+}
+
+void Map31::encounter() {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(7) + 5;
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(8, 12);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+}
+
+void Map31::hostile() {
+ SoundMessage msg(
+ STRING["maps.map31.flash"],
+ []() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._condition = ERADICATED;
+ }
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
+}
+
+void Map31::neutral() {
+ _data[VAL1]--;
+ encounter();
+}
+
+void Map31::friendly() {
+ send(SoundMessage(STRING["maps.map31.varnlings"]));
+ g_maps->clearSpecial();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map31.h b/engines/mm/mm1/maps/map31.h
index 26efc6c5fcb..a74acd67524 100644
--- a/engines/mm/mm1/maps/map31.h
+++ b/engines/mm/mm1/maps/map31.h
@@ -22,27 +22,57 @@
#ifndef MM1_MAPS_MAP31_H
#define MM1_MAPS_MAP31_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_desert.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map31 : public Map {
+class Map31 : public MapDesert {
typedef void (Map31:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special06();
- const SpecialFn SPECIAL_FN[1] = {
- &Map31::special00
+ const SpecialFn SPECIAL_FN[7] = {
+ &Map31::special00,
+ &Map31::special01,
+ &Map31::special02,
+ &Map31::special02,
+ &Map31::special02,
+ &Map31::special02,
+ &Map31::special06
};
public:
- Map31() : Map(31, "areae2", 0x706) {}
+ Map31() : MapDesert(31, "areae2", 0x706, _data[80],
+ MapDesert::RND_BASIC) {}
/**
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Starts an encounter
+ */
+ void encounter();
+
+ /**
+ * Called if you attack the alien
+ */
+ void hostile();
+
+ /**
+ * Called if you specify neutral for alien
+ */
+ void neutral();
+
+ /**
+ * Called if you select to act friendly to the alien
+ */
+ void friendly();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map_desert.cpp b/engines/mm/mm1/maps/map_desert.cpp
new file mode 100644
index 00000000000..ddbfa2e78f4
--- /dev/null
+++ b/engines/mm/mm1/maps/map_desert.cpp
@@ -0,0 +1,118 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/maps/map_desert.h"
+#include "mm/mm1/events.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+void MapDesert::desert() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ SoundMessage msg;
+ msg._lines.push_back(Line(0, 1, STRING["maps.desert.its_hot"]));
+
+ // Check whether party has the desert map
+ bool hasMap = g_globals->_party.hasItem(MAP_OF_DESERT_ID);
+ if (!hasMap) {
+ msg._lines.push_back(Line(0, 2, STRING["maps.desert.lost"]));
+ lost();
+ }
+
+ _deadCount = 0;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ if (!(c._condition & BAD_CONDITION)) {
+ if (c._food) {
+ // Take away food first
+ c._food--;
+
+ } else if (c._endurance) {
+ // Then decrease endurance when the food runs out
+ c._endurance._current--;
+
+ } else {
+ // When endurance reaches, character becomes living impaired
+ c._condition = DEAD | BAD_CONDITION;
+ _deadCount++;
+ }
+ }
+ }
+
+ if (_deadCount)
+ g_events->findView("GameParty")->redraw();
+
+ switch (_randomMode) {
+ case RND_BASIC:
+ if (getRandomNumber(100) == 100)
+ enc.execute();
+ break;
+
+ case RND_FULL:
+ switch (getRandomNumber(200)) {
+ case 20:
+ msg._lines.push_back(Line(0, msg._lines.back().y + 1,
+ STRING["maps.desert.whirlwind"]));
+ Sound::sound(SOUND_3);
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(15), getRandomNumber(15));
+
+ send(msg);
+ updateGame();
+ return;
+
+ case 30:
+ msg._lines.push_back(Line(0, msg._lines.back().y + 1,
+ STRING["maps.desert.sandstorm"]));
+ Sound::sound(SOUND_3);
+ reduceHP();
+ break;
+
+ case 199:
+ case 200:
+ g_globals->_encounters.execute();
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ send(msg);
+}
+
+void MapDesert::lost() {
+ if (getRandomNumber(2) == 1) {
+ g_maps->turnLeft();
+ } else {
+ g_maps->turnRight();
+ }
+}
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/maps/map_desert.h b/engines/mm/mm1/maps/map_desert.h
new file mode 100644
index 00000000000..6e42ff4348d
--- /dev/null
+++ b/engines/mm/mm1/maps/map_desert.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_MAPS_MAP_DESERT_H
+#define MM1_MAPS_MAP_DESERT_H
+
+#include "mm/mm1/maps/map.h"
+
+namespace MM {
+namespace MM1 {
+namespace Maps {
+
+class MapDesert : public Map {
+protected:
+ enum RandomMode { RND_BASIC, RND_FULL };
+private:
+ byte &_deadCount;
+ RandomMode _randomMode;
+
+ /**
+ * Randomly turns the party left or right
+ */
+ void lost();
+
+protected:
+ /**
+ * Handles the common part of special from desert maps
+ * dealing with being lost, and dying
+ */
+ void desert();
+
+public:
+ /**
+ * Constructor
+ */
+ MapDesert(uint index, const Common::String &name, uint16 id,
+ byte &deadCount, RandomMode rndMode) :
+ Map(index, name, id), _deadCount(deadCount), _randomMode(rndMode) {}
+};
+
+} // namespace Maps
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index d6523a10e0e..5b04be7dacf 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -43,6 +43,7 @@
#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
+#include "mm/mm1/views/maps/alien.h"
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
#include "mm/mm1/views/maps/ice_princess.h"
@@ -85,6 +86,7 @@ private:
Views::Locations::Temple _temple;
Views::Locations::Training _training;
+ Views::Maps::Alien _alien;
Views::Maps::Arrested _arrested;
Views::Maps::Chess _chess;
Views::Maps::IcePrincess _icePrincess;
diff --git a/engines/mm/mm1/views/maps/alien.cpp b/engines/mm/mm1/views/maps/alien.cpp
new file mode 100644
index 00000000000..dadc911d784
--- /dev/null
+++ b/engines/mm/mm1/views/maps/alien.cpp
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/alien.h"
+#include "mm/mm1/maps/map31.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+Alien::Alien() : TextView("Alien") {
+ _bounds = getLineBounds(20, 24);
+}
+
+void Alien::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map31.alien"]);
+}
+
+bool Alien::msgKeypress(const KeypressMessage &msg) {
+ MM1::Maps::Map31 &map = *static_cast<MM1::Maps::Map31 *>(
+ g_maps->_currentMap);
+
+ switch (msg.keycode) {
+ case Common::KEYCODE_a:
+ close();
+ map.hostile();
+ break;
+ case Common::KEYCODE_b:
+ close();
+ map.neutral();
+ break;
+ case Common::KEYCODE_c:
+ close();
+ map.friendly();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/alien.h b/engines/mm/mm1/views/maps/alien.h
new file mode 100644
index 00000000000..e14bcd63bf3
--- /dev/null
+++ b/engines/mm/mm1/views/maps/alien.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_ALIEN_H
+#define MM1_VIEWS_MAPS_ALIEN_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Alien : public TextView {
+public:
+ Alien();
+ virtual ~Alien() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/maps/giant.cpp b/engines/mm/mm1/views/maps/giant.cpp
new file mode 100644
index 00000000000..fc074d9fd39
--- /dev/null
+++ b/engines/mm/mm1/views/maps/giant.cpp
@@ -0,0 +1,136 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/giant.h"
+#include "mm/mm1/maps/map30.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+Giant::Giant() : TextView("Giant") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Giant::msgFocus(const FocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_PARTY_MENUS);
+ return TextView::msgFocus(msg);
+}
+
+bool Giant::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return msgUnfocus(msg);
+}
+
+void Giant::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map30.giant"]);
+}
+
+bool Giant::msgKeypress(const KeypressMessage &msg) {
+ if (isDelayActive()) {
+ cancelDelay();
+ redraw();
+ } else if (msg.keycode < Common::KEYCODE_1 ||
+ msg.keycode > Common::KEYCODE_6) {
+ close();
+ } else {
+ uint charIndex = msg.keycode - Common::KEYCODE_1;
+ charSelected(charIndex);
+ }
+
+ return true;
+}
+
+bool Giant::msgAction(const ActionMessage &msg) {
+ if (isDelayActive()) {
+ cancelDelay();
+ redraw();
+ } else if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ uint idx = msg._action - KEYBIND_VIEW_PARTY1;
+ charSelected(idx);
+ }
+
+ return true;
+}
+
+void Giant::charSelected(uint charIndex) {
+ if (charIndex >= g_globals->_party.size())
+ return;
+
+ Character &c = g_globals->_party[charIndex];
+ g_globals->_currCharacter = &c;
+
+ if ((c._flags[1] & ~CHARFLAG1_WORTHY) == ~CHARFLAG1_WORTHY)
+ worthy();
+ else
+ unworthy();
+}
+
+void Giant::timeout() {
+ redraw();
+}
+
+void Giant::worthy() {
+ Character &c = *g_globals->_currCharacter;
+ int val = ((c._v6e + 1) / 2) * 256;
+ c._exp += val;
+
+ Common::String line = Common::String::format(
+ STRING["maps.map30.worthy"].c_str(), '0' + (c._v6e / 5));
+ line = Common::String::format("%s%d %s",
+ line.c_str(), val, STRING["maps.map30.experience"].c_str());
+
+ if (c._v6e & 0x80) {
+ int attrNum = getRandomNumber(7) - 1;
+ line += Common::String::format(", +3 %s",
+ STRING[Common::String::format("maps.map30.attributes.%d", attrNum)].c_str());
+
+ AttributePair &attrib = c.getAttribute(attrNum);
+ if (attrib._base < 43)
+ attrib._current = attrib._base = attrib._base + 3;
+ }
+
+ c._v6e = 0;
+
+ clearSurface();
+ writeString(0, 1, line);
+ Sound::sound(SOUND_2);
+
+ delaySeconds(5);
+}
+
+void Giant::unworthy() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map30.unworthy"]);
+ Sound::sound(SOUND_2);
+
+ delaySeconds(5);
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/giant.h b/engines/mm/mm1/views/maps/giant.h
new file mode 100644
index 00000000000..060fbf84dda
--- /dev/null
+++ b/engines/mm/mm1/views/maps/giant.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_GIANT_H
+#define MM1_VIEWS_MAPS_GIANT_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Giant : public TextView {
+private:
+ void charSelected(uint charIndex);
+ void worthy();
+ void unworthy();
+public:
+ Giant();
+ virtual ~Giant() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgAction(const ActionMessage &msg) override;
+ void timeout() override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 388703f9028..71dfe9a770c 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -51,9 +51,11 @@ MODULE_OBJS := \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
mm1/views/maps/access_code.o \
+ mm1/views/maps/alien.o \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
mm1/views/maps/chess.o \
+ mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
mm1/views/maps/resistances.o \
@@ -105,6 +107,7 @@ MODULE_OBJS := \
mm1/views_enh/locations/temple.o \
mm1/maps/maps.o \
mm1/maps/map.o \
+ mm1/maps/map_desert.o \
mm1/maps/map_town.o \
mm1/maps/map00.o \
mm1/maps/map01.o \
Commit: 23d17a9e5a3f795010639068a458ee9f65e1d703
https://github.com/scummvm/scummvm/commit/23d17a9e5a3f795010639068a458ee9f65e1d703
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Changed desert maps to use MapDesert base class
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map26.cpp
engines/mm/mm1/maps/map26.h
engines/mm/mm1/maps/map27.cpp
engines/mm/mm1/maps/map27.h
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/map30.h
engines/mm/mm1/maps/map_desert.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 2e952f3fee2..ef2fbf29c43 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -822,6 +822,8 @@ maps:
desert:
its_hot: "IT'S HOT... "
youre_lost: "YOU'RE LOST!!!"
+ whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
+ sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
map00:
blacksmith: """B AND B BLACKSMITHING"""
@@ -1182,10 +1184,6 @@ maps:
trading_post: "A SMALL TRIBE OF DESERT NOMADS HAVE\nESTABLISHED A TRADING POST HERE.\nTRADE ITEM (Y/N)?"
leader_nothing: "YOUR LEADER HAS NOTHING TO TRADE!"
kilburn: "KILBURN, C-3 6-14"
- its_hot: "IT'S HOT... "
- lost: "YOU'RE LOST!!!"
- whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
- sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
map27:
pool: "THE POOL OF WISDOM GRANTS THOSE WHO ARE\nWORTHY +4 PERSONALITY."
@@ -1195,8 +1193,6 @@ maps:
alignment: "YOUR ALIGNMENT IS RESTORED!"
curses: "ALL CURSES ARE REMOVED!"
sign: "THE CLERICS OF THE S. SHALL DEEM YOU\nWORTHY, IF YOU CAN FIND THEM!"
- its_hot: "IT'S HOT... "
- lost: "YOU'RE LOST!!!"
map28:
cave: "A CAVE, ENTER (Y/N)?"
@@ -1226,10 +1222,6 @@ maps:
map30:
passage: "PASSAGE TO DUSK, ENTER (Y/N)?"
ruins: "RUINS OF CASTLE DRAGADUNE, ENTER (Y/N)?"
- its_hot: "IT'S HOT... "
- youre_lost: "YOU'RE LOST!!!"
- whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
- sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
hourglass: "AT THE CENTER OF THE LAND THAT TIME\nFORGOT STANDS AN HOURGLASS,TURN IT(Y/N)?"
unworthy: "NOT WORTHY!"
worthy: "YOUR ACTIONS REFLECT YOUR VIEWS %d OF 6\n+"
diff --git a/engines/mm/mm1/maps/map26.cpp b/engines/mm/mm1/maps/map26.cpp
index 3eb78ba210a..007c1ac6e51 100644
--- a/engines/mm/mm1/maps/map26.cpp
+++ b/engines/mm/mm1/maps/map26.cpp
@@ -29,7 +29,7 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 247
+#define VAL1 67
void Map26::special() {
// Scan for special actions on the map cell
@@ -46,67 +46,7 @@ void Map26::special() {
}
}
- SoundMessage msg;
- msg._lines.push_back(Line(0, 1, STRING["maps.map26.its_hot"]));
-
- // Check whether party has the desert map
- bool hasMap = g_globals->_party.hasItem(MAP_OF_DESERT_ID);
- if (!hasMap) {
- msg._lines.push_back(Line(0, 2, STRING["maps.map26.lost"]));
- lost();
- }
-
- _data[VAL1] = 0;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
-
- if (c._food) {
- // Take away food first
- c._food--;
-
- } else if (c._endurance) {
- // Then decrease endurance when the food runs out
- c._endurance._current--;
-
- } else {
- // When endurance reaches, character becomes living impaired
- c._condition = DEAD | BAD_CONDITION;
- _data[VAL1]++;
- }
- }
-
- if (_data[VAL1])
- g_events->findView("GameParty")->redraw();
-
- switch (getRandomNumber(200)) {
- case 20:
- msg._lines.push_back(Line(0, msg._lines.back().y + 1,
- STRING["maps.map26.whirlwind"]));
- Sound::sound(SOUND_3);
- g_maps->_mapPos = Common::Point(
- getRandomNumber(15), getRandomNumber(15));
-
- send(msg);
- updateGame();
- return;
-
- case 30:
- msg._lines.push_back(Line(0, msg._lines.back().y + 1,
- STRING["maps.map26.sandstorm"]));
- Sound::sound(SOUND_3);
- reduceHP();
- break;
-
- case 199:
- case 200:
- g_globals->_encounters.execute();
- break;
-
- default:
- break;
- }
-
- send(msg);
+ desert();
}
void Map26::special00() {
@@ -169,14 +109,6 @@ void Map26::special03() {
send(SoundMessage(STRING["maps.map26.kilburn"]));
}
-void Map26::lost() {
- if (getRandomNumber(2) == 1) {
- g_maps->turnLeft();
- } else {
- g_maps->turnRight();
- }
-}
-
void Map26::addFlag() {
for (uint i = 0; i < g_globals->_party.size(); ++i)
g_globals->_party[i]._flags[2] |= CHARFLAG2_2;
diff --git a/engines/mm/mm1/maps/map26.h b/engines/mm/mm1/maps/map26.h
index ef28439139c..1c6729f4ca4 100644
--- a/engines/mm/mm1/maps/map26.h
+++ b/engines/mm/mm1/maps/map26.h
@@ -22,20 +22,19 @@
#ifndef MM1_MAPS_MAP26_H
#define MM1_MAPS_MAP26_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_desert.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map26 : public Map {
+class Map26 : public MapDesert {
typedef void (Map26:: *SpecialFn)();
private:
void special00();
void special01();
void special02();
void special03();
- void lost();
void addFlag();
const SpecialFn SPECIAL_FN[4] = {
@@ -45,7 +44,8 @@ private:
&Map26::special03
};
public:
- Map26() : Map(26, "aread1", 0x505) {}
+ Map26() : MapDesert(26, "aread1", 0x505,
+ _data[247], MapDesert::RND_FULL) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
index 0198b821892..a48e66ffa23 100644
--- a/engines/mm/mm1/maps/map27.cpp
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -29,8 +29,6 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 66
-
void Map27::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < 6; ++i) {
@@ -46,45 +44,7 @@ void Map27::special() {
}
}
- SoundMessage msg;
- msg._lines.push_back(Line(0, 1, STRING["maps.map27.its_hot"]));
-
- // Check whether party has the desert map
- bool hasMap = g_globals->_party.hasItem(MAP_OF_DESERT_ID);
- if (!hasMap) {
- msg._lines.push_back(Line(0, 2, STRING["maps.map27.lost"]));
- lost();
- }
-
- _data[VAL1] = 0;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
-
- if (c._food) {
- // Take away food first
- c._food--;
-
- } else if (c._endurance) {
- // Then decrease endurance when the food runs out
- c._endurance._current--;
-
- } else {
- // When endurance reaches, character becomes living impaired
- c._condition = DEAD | BAD_CONDITION;
- _data[VAL1]++;
- }
- }
-
- if (_data[VAL1])
- g_events->findView("GameParty")->redraw();
-
- if (getRandomNumber(100) == 100) {
- msg._keyCallback = [](const Common::KeyState &ks) {
- g_globals->_encounters.execute();
- };
- }
-
- send(msg);
+ desert();
}
void Map27::special00() {
@@ -163,14 +123,6 @@ void Map27::special05() {
send(SoundMessage(STRING["maps.map27.sign"]));
}
-void Map27::lost() {
- if (getRandomNumber(2) == 1) {
- g_maps->turnLeft();
- } else {
- g_maps->turnRight();
- }
-}
-
Common::String Map27::clerics(char name) {
return Common::String::format("%s %c.",
STRING["maps.map27.clerics"].c_str(), name);
diff --git a/engines/mm/mm1/maps/map27.h b/engines/mm/mm1/maps/map27.h
index 82856e7f92c..9f45bd73247 100644
--- a/engines/mm/mm1/maps/map27.h
+++ b/engines/mm/mm1/maps/map27.h
@@ -22,13 +22,13 @@
#ifndef MM1_MAPS_MAP27_H
#define MM1_MAPS_MAP27_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_desert.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map27 : public Map {
+class Map27 : public MapDesert {
typedef void (Map27:: *SpecialFn)();
private:
void special00();
@@ -37,7 +37,6 @@ private:
void special03();
void special04();
void special05();
- void lost();
Common::String clerics(char name);
const SpecialFn SPECIAL_FN[6] = {
@@ -49,7 +48,8 @@ private:
&Map27::special05
};
public:
- Map27() : Map(27, "aread2", 0xB05) {}
+ Map27() : MapDesert(27, "aread2", 0xB05,
+ _data[66], MapDesert::RND_BASIC) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index 4d45329310d..73985cea249 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -29,8 +29,6 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 137
-
static const byte MONSTER_ID1[8] = { 2, 3, 8, 10, 14, 16, 17, 7 };
static const byte MONSTER_ID2[8] = { 5, 6, 3, 8, 10, 12, 12, 12 };
@@ -66,69 +64,9 @@ void Map30::special() {
enc._levelIndex = 96;
enc.execute();
return;
- }
-
- SoundMessage msg;
- msg._lines.push_back(Line(0, 1, STRING["maps.map30.its_hot"]));
-
- // Check whether party has the desert map
- bool hasMap = g_globals->_party.hasItem(MAP_OF_DESERT_ID);
- if (!hasMap) {
- msg._lines.push_back(Line(0, 2, STRING["maps.map30.lost"]));
- lost();
- }
-
- _data[VAL1] = 0;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
-
- if (c._food) {
- // Take away food first
- c._food--;
-
- } else if (c._endurance) {
- // Then decrease endurance when the food runs out
- c._endurance._current--;
-
- } else {
- // When endurance reaches, character becomes living impaired
- c._condition = DEAD | BAD_CONDITION;
- _data[VAL1]++;
- }
- }
-
- if (_data[VAL1])
- g_events->findView("GameParty")->redraw();
-
- switch (getRandomNumber(200)) {
- case 20:
- msg._lines.push_back(Line(0, msg._lines.back().y + 1,
- STRING["maps.map30.whirlwind"]));
- Sound::sound(SOUND_3);
- g_maps->_mapPos = Common::Point(
- getRandomNumber(15), getRandomNumber(15));
-
- send(msg);
- updateGame();
- return;
-
- case 30:
- msg._lines.push_back(Line(0, msg._lines.back().y + 1,
- STRING["maps.map30.sandstorm"]));
- Sound::sound(SOUND_3);
- reduceHP();
- break;
-
- case 199:
- case 200:
- g_globals->_encounters.execute();
- break;
-
- default:
- break;
}
- send(msg);
+ desert();
}
void Map30::special00() {
@@ -173,14 +111,6 @@ void Map30::special03() {
));
}
-void Map30::lost() {
- if (getRandomNumber(2) == 1) {
- g_maps->turnLeft();
- } else {
- g_maps->turnRight();
- }
-}
-
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map30.h b/engines/mm/mm1/maps/map30.h
index 2d6ab4a2a51..56fa0025e8c 100644
--- a/engines/mm/mm1/maps/map30.h
+++ b/engines/mm/mm1/maps/map30.h
@@ -22,20 +22,19 @@
#ifndef MM1_MAPS_MAP30_H
#define MM1_MAPS_MAP30_H
-#include "mm/mm1/maps/map.h"
+#include "mm/mm1/maps/map_desert.h"
namespace MM {
namespace MM1 {
namespace Maps {
-class Map30 : public Map {
+class Map30 : public MapDesert {
typedef void (Map30:: *SpecialFn)();
private:
void special00();
void special01();
void special02();
void special03();
- void lost();
const SpecialFn SPECIAL_FN[4] = {
&Map30::special00,
@@ -44,7 +43,8 @@ private:
&Map30::special03
};
public:
- Map30() : Map(30, "areae1", 0x112) {}
+ Map30() : MapDesert(30, "areae1", 0x112,
+ _data[137], MapDesert::RND_FULL) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map_desert.cpp b/engines/mm/mm1/maps/map_desert.cpp
index ddbfa2e78f4..7ec410cfc35 100644
--- a/engines/mm/mm1/maps/map_desert.cpp
+++ b/engines/mm/mm1/maps/map_desert.cpp
@@ -67,8 +67,12 @@ void MapDesert::desert() {
switch (_randomMode) {
case RND_BASIC:
- if (getRandomNumber(100) == 100)
- enc.execute();
+ if (getRandomNumber(100) == 100) {
+ msg._ynCallback = []() {
+ g_globals->_encounters.execute();
+ };
+ msg._delaySeconds = 3;
+ }
break;
case RND_FULL:
Commit: 788d129bd01f54c0beaf756e88f6a1b9e204f8ab
https://github.com/scummvm/scummvm/commit/788d129bd01f54c0beaf756e88f6a1b9e204f8ab
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:25+01:00
Commit Message:
MM: MM1: Added map 32
Changed paths:
A engines/mm/mm1/views/maps/lion.cpp
A engines/mm/mm1/views/maps/lion.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map32.cpp
engines/mm/mm1/maps/map32.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ef2fbf29c43..35f2ad3ff6d 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1242,3 +1242,22 @@ maps:
flash: "A BRIGHT FLASH!"
varnlings: """VARNLINGS TAKE HEED! OUR PRISONER HAS\nESCAPED AND MAY BE DISGUISED AS A NOBLE.\nFIND HIS COUNTERPART TO EXPOSE HIM!"""
poof: "POOF!"
+
+ map32:
+ castle: "KING ALAMAR'S CASTLE, ENTER (Y/N)?"
+ door: "A DIAMOND DOOR!"
+ key: " USE YOUR KEY (Y/N)?"
+ statue: "STATUE OF A LION GROWLS, ""PASSWORD?""\nRESPONSE:> .........."
+ password: "IS THE PASSWORD FOR TODAY,\nLEAVE THE AREA AND CHANGE IT I MAY!"""
+ heratio: "HERATIO HARPER SINGS:"
+ music: "DISTANT HARP MUSIC..."
+ passwords:
+ 0: "MUSICAL"
+ 1: "TONES"
+ 2: "TOGETHER"
+ 3: "CLERICS"
+ 4: "SOUTH"
+ 5: "DEEM"
+ 6: "WORTHY"
+ trespassing: "TRESPASSING!"
+ correct: "CORRECT! YOU MAY PASS."
diff --git a/engines/mm/mm1/maps/map32.cpp b/engines/mm/mm1/maps/map32.cpp
index 4b60e393a49..03fd6a0c695 100644
--- a/engines/mm/mm1/maps/map32.cpp
+++ b/engines/mm/mm1/maps/map32.cpp
@@ -29,14 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 75
+#define VAL2 111
+#define PASSWORD_INDEX 393
+
void Map32::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 6; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[57 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +47,95 @@ void Map32::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (_states[g_maps->_mapOffset] == 0x55 && g_maps->_mapPos.x < 13) {
+ send(SoundMessage(STRING["maps.map32.music"]));
+ } else {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ }
}
void Map32::special00() {
+ if (!g_globals->_party.hasItem(DIAMOND_KEY_ID)) {
+ send(SoundMessage(STRING["maps.map32.door"]));
+ } else {
+ send(SoundMessage(
+ 0, 1, STRING["maps.map32.door"],
+ 0, 2, STRING["maps.map32.key"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 0);
+ g_maps->changeMap(0xb1a, 3);
+ }
+ ));
+ }
+}
+
+void Map32::special01() {
+ g_events->addView("Lion");
+}
+
+void Map32::special02() {
+ if (_data[VAL2] & 0x80) {
+ g_maps->_mapPos = Common::Point(0, 7);
+ g_maps->changeMap(0xb07, 3);
+
+ } else if (_data[VAL2] != 0) {
+ _data[VAL2] = 0;
+
+ } else {
+ send(SoundMessage(
+ STRING["maps.map32.castle"],
+ [](const Common::KeyState &ks) {
+ Map32 &map = *static_cast<Map32 *>(g_maps->_currentMap);
+ if (ks.keycode == Common::KEYCODE_y) {
+ g_events->close();
+ map[VAL2] = 0xff;
+ } else if (ks.keycode == Common::KEYCODE_n) {
+ g_events->close();
+ map[VAL2]++;
+ }
+ }
+ ));
+ }
+}
+
+void Map32::special04() {
+ if (_data[PASSWORD_INDEX] & 0x80) {
+ _data[PASSWORD_INDEX] = getRandomNumber(7) - 1;
+ }
+
+ Common::String line2 = Common::String::format("\"%s %s",
+ STRING[Common::String::format("maps.map32.passwords.%d",
+ _data[PASSWORD_INDEX])].c_str(),
+ STRING["maps.map32.password"].c_str()
+ );
+
+ send(SoundMessage(
+ 0, 1, STRING["maps.map32.heratio"],
+ 0, 2, line2
+ ));
+}
+
+void Map32::special05() {
+ if (!_data[VAL1]) {
+ g_maps->_mapPos.x--;
+ updateGame();
+ }
+}
+
+void Map32::passwordEntered(const Common::String &password) {
+ if ((_data[PASSWORD_INDEX] & 0x80) || password !=
+ STRING[Common::String::format("maps.map32.passwords.%d",
+ _data[PASSWORD_INDEX])]) {
+ g_maps->_mapPos.x--;
+ updateGame();
+
+ } else {
+ g_events->send(SoundMessage(STRING["maps.map32.correct"]));
+ _data[VAL1]++;
+ g_maps->clearSpecial();
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map32.h b/engines/mm/mm1/maps/map32.h
index 31d3a0c56cf..a0a73b6d0d1 100644
--- a/engines/mm/mm1/maps/map32.h
+++ b/engines/mm/mm1/maps/map32.h
@@ -32,9 +32,18 @@ class Map32 : public Map {
typedef void (Map32:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special04();
+ void special05();
- const SpecialFn SPECIAL_FN[1] = {
- &Map32::special00
+ const SpecialFn SPECIAL_FN[6] = {
+ &Map32::special00,
+ &Map32::special01,
+ &Map32::special02,
+ &Map32::special01,
+ &Map32::special04,
+ &Map32::special05
};
public:
Map32() : Map(32, "areae3", 0xB1A) {}
@@ -43,6 +52,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Password given to lion
+ */
+ void passwordEntered(const Common::String &password);
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 5b04be7dacf..91cb90df7bb 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -47,6 +47,7 @@
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
#include "mm/mm1/views/maps/ice_princess.h"
+#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/trivia.h"
#include "mm/mm1/views/maps/volcano_god.h"
@@ -90,6 +91,7 @@ private:
Views::Maps::Arrested _arrested;
Views::Maps::Chess _chess;
Views::Maps::IcePrincess _icePrincess;
+ Views::Maps::Lion _lion;
Views::Maps::Resistances _resistances;
Views::Maps::Trivia _trivia;
Views::Maps::VolcanoGod _volcanoGod;
diff --git a/engines/mm/mm1/views/maps/lion.cpp b/engines/mm/mm1/views/maps/lion.cpp
new file mode 100644
index 00000000000..a5016ac8ea0
--- /dev/null
+++ b/engines/mm/mm1/views/maps/lion.cpp
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/lion.h"
+#include "mm/mm1/maps/map32.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define PASSWORD_INDEX 393
+
+Lion::Lion() : AnswerEntry("Lion", Common::Point(11, 2), 10) {
+}
+
+void Lion::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map32.statue"]);
+}
+
+void Lion::answerEntered() {
+ MM1::Maps::Map32 &map = *static_cast<MM1::Maps::Map32 *>(g_maps->_currentMap);
+ map.passwordEntered(_answer);
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/lion.h b/engines/mm/mm1/views/maps/lion.h
new file mode 100644
index 00000000000..99665d28276
--- /dev/null
+++ b/engines/mm/mm1/views/maps/lion.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_LION_H
+#define MM1_VIEWS_MAPS_LION_H
+
+#include "mm/mm1/views/maps/answer_entry.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Lion : public AnswerEntry {
+protected:
+ void answerEntered() override;
+
+public:
+ Lion();
+ virtual ~Lion() {}
+
+ void draw() override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 71dfe9a770c..c575bc97f03 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -58,6 +58,7 @@ MODULE_OBJS := \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
+ mm1/views/maps/lion.o \
mm1/views/maps/resistances.o \
mm1/views/maps/trivia.o \
mm1/views/maps/volcano_god.o \
Commit: 117e96141e29eb0794c337f52bb007a0aff8440c
https://github.com/scummvm/scummvm/commit/117e96141e29eb0794c337f52bb007a0aff8440c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: In progress map 33
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/map33.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 35f2ad3ff6d..61e7ea2cafc 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1261,3 +1261,14 @@ maps:
6: "WORTHY"
trespassing: "TRESPASSING!"
correct: "CORRECT! YOU MAY PASS."
+
+ map33:
+ building: "THE FABLED BUILDING OF GOLD,\nENTER (Y/N)?"
+ slime: "ECTOPLASMIC SLIME SLUSHES BENEATH YOU!\n"
+ tombstones: "TOPPLED TOMBSTONES ABOUND!"
+ coffin: "UNEARTHED COFFIN! EXAMINE (Y/N)?"
+ crypt: "OPEN CRYPT! EXAMINE (Y/N)?"
+ corpse: "HALF BURIED CORPSE ASKS FOR HELP!\nASSIST (Y/N)?"
+ meeting: "DRAGON CITY, TOWN MEETING...\nDISRUPT (Y/N)?"
+ quicksand: "QUICKSAND!"
+ thanks: "THANKS! IT AIN'T EASY BEING A CORPSE!\nTAKE THESE..."
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index 8a0e72f4a56..d4123bc4077 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -29,14 +29,28 @@ namespace MM {
namespace MM1 {
namespace Maps {
+static const byte MONSTER_IDS11[10] = {
+ 15, 16, 15, 16, 14, 15, 4, 5, 3, 2
+};
+static const byte MONSTER_IDS12[10] = {
+ 7, 7, 8, 8, 9, 9, 10, 10, 10, 10
+};
+static const byte MONSTER_IDS21[12] = {
+ 2, 12, 7, 5, 5, 1, 2, 3, 1, 4, 5, 2
+};
+static const byte MONSTER_IDS22[12] = {
+ 5, 18, 10, 10, 11, 11, 11, 14, 13, 16, 15, 16
+};
+
void Map33::special() {
+ Game::Encounter &enc = g_globals->_encounters;
+
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 5; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[56 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +58,86 @@ void Map33::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (_states[g_maps->_mapOffset] == 0xff) {
+ if (g_maps->_mapPos.x >= 6 || g_maps->_mapPos.y < 5 ||
+ g_maps->_mapPos.y >= 8) {
+ if (g_maps->_mapPos.y < 5 && g_maps->_forwardMask != DIRMASK_N) {
+ g_events->addKeypress((Common::KeyCode)149);
+ } else {
+ InfoMessage msg(0, 1, STRING["maps.map33.slime"]);
+ Sound::sound(SOUND_2);
+
+ switch (getRandomNumber(200)) {
+ case 198: {
+ Character &c = g_globals->_party[
+ getRandomNumber(g_globals->_party.size() - 1)
+ ];
+ if (!(c._condition & BAD_CONDITION)) {
+ c._condition |= SILENCED | PARALYZED | UNCONSCIOUS;
+ c._hpBase = 0;
+ msg._lines.push_back(Line(0, 2, STRING["maps.map33.quicksand"]));
+ Sound::sound(SOUND_3);
+ }
+ break;
+ }
+
+ case 199:
+ case 200: {
+ int monsterCount = getRandomNumber(10) + 3;
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i) {
+ int idx = getRandomNumber(12) - 1;
+ enc.addMonster(MONSTER_IDS21[idx], MONSTER_IDS22[idx]);
+ }
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ } else {
+ send(SoundMessage(STRING["maps.map33.tombstones"]));
+ }
+ } else {
+ if (g_maps->_mapPos.y < 5) {
+ int monsterCount = getRandomNumber(6) + 2;
+ int idx = getRandomNumber(6) - 1;
+ int id1 = MONSTER_IDS11[idx];
+ int id2 = MONSTER_IDS12[idx];
+
+ enc.clearMonsters();
+ for (int i = 0; i < monsterCount; ++i)
+ enc.addMonster(id1, id2);
+
+ enc._flag = true;
+ enc._levelIndex = 64;
+ }
+
+ g_maps->clearSpecial();
+ enc.execute();
+ }
}
void Map33::special00() {
+
+}
+
+void Map33::special01() {
+}
+
+void Map33::special02() {
+}
+
+void Map33::special03() {
+}
+
+void Map33::special04() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map33.h b/engines/mm/mm1/maps/map33.h
index 9d16d6c1495..8c2f38e0a88 100644
--- a/engines/mm/mm1/maps/map33.h
+++ b/engines/mm/mm1/maps/map33.h
@@ -32,9 +32,17 @@ class Map33 : public Map {
typedef void (Map33:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map33::special00
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+
+ const SpecialFn SPECIAL_FN[5] = {
+ &Map33::special00,
+ &Map33::special01,
+ &Map33::special02,
+ &Map33::special03,
+ &Map33::special04
};
public:
Map33() : Map(33, "areae4", 0x11B) {}
Commit: 5163e9bae674b47ed400dbf24d6b7af76f14dcec
https://github.com/scummvm/scummvm/commit/5163e9bae674b47ed400dbf24d6b7af76f14dcec
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: Remainder of map 33
Changed paths:
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/map33.h
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index d4123bc4077..2b96ea7d8e6 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -29,6 +29,9 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 71
+#define VAL2 72
+
static const byte MONSTER_IDS11[10] = {
15, 16, 15, 16, 14, 15, 4, 5, 3, 2
};
@@ -125,19 +128,75 @@ void Map33::special() {
}
void Map33::special00() {
+ send(SoundMessage(
+ STRING["maps.map33.meeting"],
+ []() {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+
+ enc.clearMonsters();
+ for (int i = 0; i < 10; ++i)
+ enc.addMonster(MONSTER_IDS11[i], MONSTER_IDS12[i]);
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
+ ));
}
void Map33::special01() {
+ send(SoundMessage(
+ STRING["maps.map33.building"],
+ []() {
+ g_maps->_mapPos = Common::Point(0, 0);
+ g_maps->changeMap(0xf01, 3);
+ }
+ ));
}
void Map33::special02() {
+ _data[VAL1] = 12;
+ _data[VAL2] = 8;
+ search(STRING["maps.map33.coffin"]);
}
void Map33::special03() {
+ _data[VAL1] = 10;
+ _data[VAL2] = 10;
+ search(STRING["maps.map33.crypt"]);
}
void Map33::special04() {
+ send(SoundMessage(
+ STRING["maps.map33.corpse"],
+ []() {
+ g_events->send(SoundMessage(STRING["maps.map33.thanks"]));
+ g_globals->_treasure[8] = 50;
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ ));
+}
+
+void Map33::search(const Common::String &msg) {
+ send(SoundMessage(
+ msg,
+ []() {
+ Map33 &map = *static_cast<Map33 *>(g_maps->_currentMap);
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterCount = getRandomNumber(6) + 7;
+
+ enc.clearMonsters();
+ enc.addMonster(map[VAL1], map[VAL2]);
+
+ for (int i = 1; i < monsterCount; ++i)
+ enc.addMonster(10, 7);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map33.h b/engines/mm/mm1/maps/map33.h
index 8c2f38e0a88..5edf111aa89 100644
--- a/engines/mm/mm1/maps/map33.h
+++ b/engines/mm/mm1/maps/map33.h
@@ -36,6 +36,7 @@ private:
void special02();
void special03();
void special04();
+ void search(const Common::String &msg);
const SpecialFn SPECIAL_FN[5] = {
&Map33::special00,
Commit: 69962c01faa6c58454bef7b04afdaf8eb85a5ddf
https://github.com/scummvm/scummvm/commit/69962c01faa6c58454bef7b04afdaf8eb85a5ddf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: Added map 34
Changed paths:
A engines/mm/mm1/views/maps/child.cpp
A engines/mm/mm1/views/maps/child.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map34.cpp
engines/mm/mm1/maps/map34.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 61e7ea2cafc..e185d8050db 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1272,3 +1272,27 @@ maps:
meeting: "DRAGON CITY, TOWN MEETING...\nDISRUPT (Y/N)?"
quicksand: "QUICKSAND!"
thanks: "THANKS! IT AIN'T EASY BEING A CORPSE!\nTAKE THESE..."
+
+ map34:
+ statue: "A GRUESOME STATUE SAYS:\n""START AT 15-7 AND WALK TO DOOM!"""
+ banner: "A BANNER READS:\nTHE ENDLESS SPIRAL!!!"
+ sign: "A SIGN ABOVE THE DOOR READS:\nMONSTER BREEDING GROUNDS, KEEP OUT!"
+ machine: "A LOUD MACHINE PULSATES RHYTHMICALLY."
+ box: "A METALIC BOX ECHOES:\n""INTRUDER ALERT!"""
+ message1: "SCRATCHED ON THE WALL:\nSEARCH AFTER THE CANINE REWARDS YOU!"
+ message2: "SCRAWLED ON THE WALL:\nFOR THE WORLD IS HOLLOW AND I HAVE\nTOUCHED THE SKY!"
+ message3: "ETCHED IN SILVER, MESSAGE D READS:\n//SV/21;-22R,;DU1RS0"
+ message4: "WRITTEN IN BLUE BLOOD:\nTHE CANINE HAS THE KEY!"
+ message5: "ETCHED IN SILVER:\nMESSAGE INTERLEAVE 'FEDBAC'"
+ message6: "ETCHED IN GOLD:\nMESSAGE INTERLEAVE '8,5,3,9,1,4,6,2,7'"
+ message7: "WRITTEN ON THE WALL:\nJUMP THREE TIMES TO REACH CENTER."
+ child: "A SMALL CHILD SHIVERS FEARFULLY AS YOU\nAPPROACH.\n\n"
+ options1: "OPTIONS: 1) SET THE PRISONER FREE.\n"
+ options2: "2) TORMENT THE PRISONER.\n"
+ options3: "3) LEAVE WITHOUT DISTURBING."
+ prisoner_flees: "THE PRISONER FLEES!"
+ prisoner_cowers: "THE PRISONER COWERS!"
+ passage: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ door: "A GOLDEN DOOR REPELS YOU!"
+ alamar1: "SUSPENDED IN A FORCEFIELD IS THE BODY\nOF A MAN ENCLOSED IN AN IRON SUIT.\nTELEPATHIC COMMUNICATION:""I AM THE TRUE\nKING ALAMAR, IMPRISONED BY A DEMONIC\nALIEN BEING! CONFRONT HIM WITH THIS EYE\nOF GOROS AND YOU SHALL SEE HIS TRUE\nSELF."
+ alamar2: "THE FATE OF THE REALM IS AT STAKE."""
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 09be5b5042d..3602c402da4 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -121,6 +121,39 @@ enum CharFlags7 {
CHARFLAG7_80 = 0x80
};
+enum CharFlags8 {
+ CHARFLAG8_1 = 1,
+ CHARFLAG8_2 = 2,
+ CHARFLAG8_4 = 4,
+ CHARFLAG8_8 = 8,
+ CHARFLAG8_10 = 0x10,
+ CHARFLAG8_20 = 0x20,
+ CHARFLAG8_40 = 0x40,
+ CHARFLAG8_80 = 0x80
+};
+
+enum CharFlags9 {
+ CHARFLAG9_1 = 1,
+ CHARFLAG9_2 = 2,
+ CHARFLAG9_4 = 4,
+ CHARFLAG9_8 = 8,
+ CHARFLAG9_10 = 0x10,
+ CHARFLAG9_20 = 0x20,
+ CHARFLAG9_40 = 0x40,
+ CHARFLAG9_80 = 0x80
+};
+
+enum CharFlags10 {
+ CHARFLAG10_1 = 1,
+ CHARFLAG10_2 = 2,
+ CHARFLAG10_4 = 4,
+ CHARFLAG10_8 = 8,
+ CHARFLAG10_10 = 0x10,
+ CHARFLAG10_20 = 0x20,
+ CHARFLAG10_40 = 0x40,
+ CHARFLAG10_80 = 0x80
+};
+
enum CharFlags11 {
CHARFLAG11_GOT_ENDURANCE = 1,
CHARFLAG11_PERSONALITY = 2,
@@ -130,6 +163,28 @@ enum CharFlags11 {
CHARFLAG11_GOT_SPEED = 0x20
};
+enum CharFlags12 {
+ CHARFLAG12_1 = 1,
+ CHARFLAG12_2 = 2,
+ CHARFLAG12_4 = 4,
+ CHARFLAG12_8 = 8,
+ CHARFLAG12_10 = 0x10,
+ CHARFLAG12_20 = 0x20,
+ CHARFLAG12_40 = 0x40,
+ CHARFLAG12_80 = 0x80
+};
+
+enum CharFlags13 {
+ CHARFLAG13_1 = 1,
+ CHARFLAG13_2 = 2,
+ CHARFLAG13_4 = 4,
+ CHARFLAG13_8 = 8,
+ CHARFLAG13_10 = 0x10,
+ CHARFLAG13_20 = 0x20,
+ CHARFLAG13_40 = 0x40,
+ CHARFLAG13_80 = 0x80
+};
+
enum CharFlags14 {
CHARFLAG14_80 = 0x80
};
@@ -352,9 +407,9 @@ struct Character : public PrimaryAttributes {
// TODO: Figure out what these are
AttributePair _physicalAttr, _missileAttr;
- int _v6c;
+ byte _v6c;
byte _quest = 0;
- int _v6e;
+ byte _v6e;
int _alignmentCtr;
byte _flags[14];
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 857fd980f29..92fabf97d45 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -36,6 +36,8 @@ enum ItemId {
RUBY_WHISTLE_ID = 232,
CORAL_KEY_ID = 236,
BRONZE_KEY_ID = 237,
+ SILVER_KEY_ID = 238,
+ GOLD_KEY_ID = 239,
DIAMOND_KEY_ID = 240,
CACTUS_NECTAR_ID = 241,
MAP_OF_DESERT_ID = 242,
@@ -43,6 +45,7 @@ enum ItemId {
W_QUEEN_IDOL_ID = 249,
PIRATES_MAP_A_ID = 250,
PIRATES_MAP_B_ID = 251,
+ EYE_OF_GOROS_ID = 254,
USELESS_ITEM_ID = 255
};
diff --git a/engines/mm/mm1/maps/map34.cpp b/engines/mm/mm1/maps/map34.cpp
index da6367dfda9..c65991ef02b 100644
--- a/engines/mm/mm1/maps/map34.cpp
+++ b/engines/mm/mm1/maps/map34.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 1238
+
void Map34::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[74 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,125 @@ void Map34::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map34::special00() {
+ g_events->addView("Child");
+}
+
+void Map34::special01() {
+ send(SoundMessage(
+ STRING["maps.map34.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 15);
+ g_maps->changeMap(0xf01, 2);
+ }
+ ));
+}
+
+void Map34::special02() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if ((c._flags[13] & CHARFLAG13_40) || c.hasItem(EYE_OF_GOROS_ID)) {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ return;
+ }
+ }
+
+ Sound::sound2(SOUND_2);
+
+ InfoMessage msg(
+ 0, 0, STRING["alamar1"],
+ 0, 7, STRING["alamar2"]
+ );
+ msg._largeMessage = true;
+ send(msg);
+}
+
+void Map34::special03() {
+ send(SoundMessage(STRING["maps.map34.message3"]));
+}
+
+void Map34::special04() {
+ send(SoundMessage(STRING["maps.map34.message4"]));
+}
+
+void Map34::special05() {
+ send(SoundMessage(STRING["maps.map34.message5"]));
+}
+
+void Map34::special06() {
+ send(SoundMessage(STRING["maps.map34.message6"]));
+}
+
+void Map34::special07() {
+ if (g_globals->_party.hasItem(GOLD_KEY_ID)) {
+ checkPartyDead();
+ } else {
+ send(SoundMessage(STRING["maps.map34.door"]));
+ g_maps->_mapPos.y--;
+ updateGame();
+ }
+}
+
+void Map34::special08() {
+ send(SoundMessage(STRING["maps.map34.statue"]));
+}
+
+void Map34::special09() {
+ send(SoundMessage(STRING["maps.map34.banner"]));
+}
+
+void Map34::special10() {
+ g_maps->_mapPos.x++;
+ g_maps->_mapPos.y--;
+ updateGame();
+}
+
+void Map34::special12() {
+ g_maps->_mapPos.x--;
+ g_maps->_mapPos.y++;
+ updateGame();
+}
+
+void Map34::special13() {
+ send(SoundMessage(STRING["maps.map34.sign"]));
+}
+
+void Map34::special16() {
+ send(SoundMessage(STRING["maps.map34.machine"]));
+}
+
+void Map34::special17() {
+ send(SoundMessage(STRING["maps.map34.box"]));
+ _data[MAP_47] = 9;
+ _data[VAL1] = 9;
+}
+
+void Map34::special18() {
+ send(SoundMessage(STRING["maps.map34.message1"]));
+}
+
+void Map34::special19() {
+ send(SoundMessage(STRING["maps.map34.message2"]));
+}
+
+void Map34::special20() {
+ if (_data[VAL1]) {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ } else {
+ none160();
+ }
+}
+
+void Map34::special21() {
+ send(SoundMessage(STRING["maps.map34.message7"]));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map34.h b/engines/mm/mm1/maps/map34.h
index 9dfcf87618b..f879c01b60b 100644
--- a/engines/mm/mm1/maps/map34.h
+++ b/engines/mm/mm1/maps/map34.h
@@ -32,9 +32,49 @@ class Map34 : public Map {
typedef void (Map34:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special12();
+ void special13();
+ void special16();
+ void special17();
+ void special18();
+ void special19();
+ void special20();
+ void special21();
- const SpecialFn SPECIAL_FN[1] = {
- &Map34::special00
+ const SpecialFn SPECIAL_FN[23] = {
+ &Map34::special00,
+ &Map34::special01,
+ &Map34::special02,
+ &Map34::special03,
+ &Map34::special04,
+ &Map34::special05,
+ &Map34::special06,
+ &Map34::special07,
+ &Map34::special08,
+ &Map34::special09,
+ &Map34::special10,
+ &Map34::special10,
+ &Map34::special12,
+ &Map34::special13,
+ &Map34::special13,
+ &Map34::special13,
+ &Map34::special16,
+ &Map34::special17,
+ &Map34::special18,
+ &Map34::special19,
+ &Map34::special20,
+ &Map34::special21,
+ &Map34::special01
};
public:
Map34() : Map(34, "doom", 0x706) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 91cb90df7bb..0afa9a4055c 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -46,6 +46,7 @@
#include "mm/mm1/views/maps/alien.h"
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
+#include "mm/mm1/views/maps/child.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/resistances.h"
@@ -90,6 +91,7 @@ private:
Views::Maps::Alien _alien;
Views::Maps::Arrested _arrested;
Views::Maps::Chess _chess;
+ Views::Maps::Child _child;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Lion _lion;
Views::Maps::Resistances _resistances;
diff --git a/engines/mm/mm1/views/maps/child.cpp b/engines/mm/mm1/views/maps/child.cpp
new file mode 100644
index 00000000000..b7c652e793f
--- /dev/null
+++ b/engines/mm/mm1/views/maps/child.cpp
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/Child.h"
+#include "mm/mm1/maps/map34.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+Child::Child() : TextView("Child") {
+ _bounds = getLineBounds(17, 24);
+}
+
+void Child::draw() {
+ clearSurface();
+ writeString(0, 0, STRING["maps.map34.child"]);
+ writeString(0, 3, STRING["maps.map34.options1"]);
+ writeString(10, 4, STRING["maps.map34.options2"]);
+ writeString(10, 5, STRING["maps.map34.options3"]);
+}
+
+bool Child::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode < Common::KEYCODE_1 || msg.keycode > Common::KEYCODE_3)
+ return true;
+
+ Common::String line;
+ int align;
+ switch (msg.keycode) {
+ case Common::KEYCODE_1:
+ line = STRING["maps.map34.prisoner_flees"];
+ align = GOOD;
+ break;
+
+ case Common::KEYCODE_2:
+ line = STRING["maps.map34.prisoner_cowers"];
+ align = EVIL;
+ break;
+
+ default:
+ align = NEUTRAL;
+ break;
+ }
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ if (!(c._flags[1] & CHARFLAG1_4)) {
+ c._flags[1] |= CHARFLAG1_4;
+ if (align == c._alignment)
+ c._v6e += 32;
+ }
+ }
+
+ findView("GameParty")->redraw();
+ if (align != NEUTRAL) {
+ clearSurface();
+ writeString(0, 1, line);
+ Sound::sound(SOUND_2);
+ }
+
+ close();
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/child.h b/engines/mm/mm1/views/maps/child.h
new file mode 100644
index 00000000000..9c57402e3be
--- /dev/null
+++ b/engines/mm/mm1/views/maps/child.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_CHILD_H
+#define MM1_VIEWS_MAPS_CHILD_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Child : public TextView {
+public:
+ Child();
+ virtual ~Child() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c575bc97f03..98ae76db4d4 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -55,6 +55,7 @@ MODULE_OBJS := \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
mm1/views/maps/chess.o \
+ mm1/views/maps/child.o \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
Commit: b149ce245ce619167239fcdcc044d661c9250a56
https://github.com/scummvm/scummvm/commit/b149ce245ce619167239fcdcc044d661c9250a56
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: Made common prisoner view class
Changed paths:
A engines/mm/mm1/views/maps/prisoners.cpp
A engines/mm/mm1/views/maps/prisoners.h
R engines/mm/mm1/views/maps/child.cpp
R engines/mm/mm1/views/maps/child.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map34.cpp
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map35.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index e185d8050db..8e023f56e69 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -825,6 +825,17 @@ maps:
whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
+ prisoners:
+ child: "A SMALL CHILD SHIVERS FEARFULLY AS YOU\nAPPROACH.\n\n"
+ man: "MAN IN SHACKLES MOANS IN AGONY!\n\n"
+ cloaked: "A MYSTERIOUS CLOAKED FIGURE, BOUND AND\nGAGGED, LIES MOTIONLESS IN THE CORNER.\n\n"
+ demon: "A VICIOUS DEMON LUNGES AT THE PARTY,\nRESTRAINED ONLY BY A COLLAR AND CHAIN!\n\n"
+ options1: "OPTIONS: 1) SET THE PRISONER FREE.\n"
+ options2: "2) TORMENT THE PRISONER.\n"
+ options3: "3) LEAVE WITHOUT DISTURBING."
+ flees: "THE PRISONER FLEES!"
+ cowers: "THE PRISONER COWERS!"
+
map00:
blacksmith: """B AND B BLACKSMITHING"""
inn: """THE INN OF SORPIGAL"""
@@ -1286,12 +1297,6 @@ maps:
message5: "ETCHED IN SILVER:\nMESSAGE INTERLEAVE 'FEDBAC'"
message6: "ETCHED IN GOLD:\nMESSAGE INTERLEAVE '8,5,3,9,1,4,6,2,7'"
message7: "WRITTEN ON THE WALL:\nJUMP THREE TIMES TO REACH CENTER."
- child: "A SMALL CHILD SHIVERS FEARFULLY AS YOU\nAPPROACH.\n\n"
- options1: "OPTIONS: 1) SET THE PRISONER FREE.\n"
- options2: "2) TORMENT THE PRISONER.\n"
- options3: "3) LEAVE WITHOUT DISTURBING."
- prisoner_flees: "THE PRISONER FLEES!"
- prisoner_cowers: "THE PRISONER COWERS!"
passage: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
door: "A GOLDEN DOOR REPELS YOU!"
alamar1: "SUSPENDED IN A FORCEFIELD IS THE BODY\nOF A MAN ENCLOSED IN AN IRON SUIT.\nTELEPATHIC COMMUNICATION:""I AM THE TRUE\nKING ALAMAR, IMPRISONED BY A DEMONIC\nALIEN BEING! CONFRONT HIM WITH THIS EYE\nOF GOROS AND YOU SHALL SEE HIS TRUE\nSELF."
diff --git a/engines/mm/mm1/maps/map34.cpp b/engines/mm/mm1/maps/map34.cpp
index c65991ef02b..2f68914ebc6 100644
--- a/engines/mm/mm1/maps/map34.cpp
+++ b/engines/mm/mm1/maps/map34.cpp
@@ -52,7 +52,7 @@ void Map34::special() {
}
void Map34::special00() {
- g_events->addView("Child");
+ g_events->addView("ChildPrisoner");
}
void Map34::special01() {
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index b70b70bc9e7..f246850eb2f 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -31,11 +31,11 @@ namespace Maps {
void Map35::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 11; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[62 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +44,38 @@ void Map35::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map35::special00() {
+ g_events->addView("ManPrisoner");
+}
+
+void Map35::special01() {
+}
+
+void Map35::special02() {
+}
+
+void Map35::special03() {
+}
+
+void Map35::special04() {
+}
+
+void Map35::special05() {
+}
+
+void Map35::special06() {
+}
+
+void Map35::special07() {
+}
+
+void Map35::special09() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map35.h b/engines/mm/mm1/maps/map35.h
index cf595cf44a0..1064706fe39 100644
--- a/engines/mm/mm1/maps/map35.h
+++ b/engines/mm/mm1/maps/map35.h
@@ -32,9 +32,27 @@ class Map35 : public Map {
typedef void (Map35:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special09();
- const SpecialFn SPECIAL_FN[1] = {
- &Map35::special00
+ const SpecialFn SPECIAL_FN[11] = {
+ &Map35::special00,
+ &Map35::special01,
+ &Map35::special02,
+ &Map35::special03,
+ &Map35::special04,
+ &Map35::special05,
+ &Map35::special06,
+ &Map35::special07,
+ &Map35::special07,
+ &Map35::special09,
+ &Map35::special09
};
public:
Map35() : Map(35, "blackrn", 0xF08) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 0afa9a4055c..fda980c2dcf 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -46,9 +46,9 @@
#include "mm/mm1/views/maps/alien.h"
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
-#include "mm/mm1/views/maps/child.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/lion.h"
+#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/trivia.h"
#include "mm/mm1/views/maps/volcano_god.h"
@@ -91,7 +91,10 @@ private:
Views::Maps::Alien _alien;
Views::Maps::Arrested _arrested;
Views::Maps::Chess _chess;
- Views::Maps::Child _child;
+ Views::Maps::ChildPrisoner _childPrisoner;
+ Views::Maps::CloakedPrisoner _cloakedPrisoner;
+ Views::Maps::DemonPrisoner _demonPrisoner;
+ Views::Maps::ManPrisoner _manPrisoner;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Lion _lion;
Views::Maps::Resistances _resistances;
diff --git a/engines/mm/mm1/views/maps/child.cpp b/engines/mm/mm1/views/maps/prisoners.cpp
similarity index 55%
rename from engines/mm/mm1/views/maps/child.cpp
rename to engines/mm/mm1/views/maps/prisoners.cpp
index b7c652e793f..b60666938fb 100644
--- a/engines/mm/mm1/views/maps/child.cpp
+++ b/engines/mm/mm1/views/maps/prisoners.cpp
@@ -19,8 +19,7 @@
*
*/
-#include "mm/mm1/views/maps/Child.h"
-#include "mm/mm1/maps/map34.h"
+#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
@@ -29,19 +28,24 @@ namespace MM1 {
namespace Views {
namespace Maps {
-Child::Child() : TextView("Child") {
+Prisoner::Prisoner(const Common::String &name, const Common::String &line1,
+ byte flag, Alignment freeAlignment, Alignment leaveAlignment) :
+ TextView(name), _line1(line1), _flag(flag),
+ _freeAlignment(freeAlignment), _leaveAlignment(leaveAlignment) {
_bounds = getLineBounds(17, 24);
}
-void Child::draw() {
+void Prisoner::draw() {
clearSurface();
- writeString(0, 0, STRING["maps.map34.child"]);
- writeString(0, 3, STRING["maps.map34.options1"]);
- writeString(10, 4, STRING["maps.map34.options2"]);
- writeString(10, 5, STRING["maps.map34.options3"]);
+ writeString(0, 0, _line1);
+ writeString(0, 3, STRING["maps.prisoners.options1"]);
+ _textPos.x = 10;
+ writeString(STRING["maps.prisoners.options2"]);
+ _textPos.x = 10;
+ writeString(STRING["maps.prisoners.options3"]);
}
-bool Child::msgKeypress(const KeypressMessage &msg) {
+bool Prisoner::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode < Common::KEYCODE_1 || msg.keycode > Common::KEYCODE_3)
return true;
@@ -49,13 +53,13 @@ bool Child::msgKeypress(const KeypressMessage &msg) {
int align;
switch (msg.keycode) {
case Common::KEYCODE_1:
- line = STRING["maps.map34.prisoner_flees"];
- align = GOOD;
+ line = STRING["maps.prisoners.flees"];
+ align = _freeAlignment;
break;
case Common::KEYCODE_2:
- line = STRING["maps.map34.prisoner_cowers"];
- align = EVIL;
+ line = STRING["maps.prisoners.cowers"];
+ align = _leaveAlignment;
break;
default:
@@ -66,8 +70,8 @@ bool Child::msgKeypress(const KeypressMessage &msg) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- if (!(c._flags[1] & CHARFLAG1_4)) {
- c._flags[1] |= CHARFLAG1_4;
+ if (!(c._flags[1] & _flag)) {
+ c._flags[1] |= _flag;
if (align == c._alignment)
c._v6e += 32;
}
@@ -84,6 +88,28 @@ bool Child::msgKeypress(const KeypressMessage &msg) {
return true;
}
+/*------------------------------------------------------------------------*/
+
+ChildPrisoner::ChildPrisoner() :
+ Prisoner("ChildPrisoner", STRING["maps.prisoners.child"],
+ CHARFLAG1_4, GOOD, EVIL) {
+}
+
+ManPrisoner::ManPrisoner() :
+ Prisoner("ManPrisoner", STRING["maps.prisoners.man"],
+ CHARFLAG1_20, EVIL, GOOD) {
+}
+
+CloakedPrisoner::CloakedPrisoner() :
+ Prisoner("CloakedPrisoner", STRING["maps.prisoners.cloaked"],
+ CHARFLAG1_40, EVIL, GOOD) {
+}
+
+DemonPrisoner::DemonPrisoner() :
+ Prisoner("DemonPrisoner", STRING["maps.prisoners.demon"],
+ CHARFLAG1_10, EVIL, GOOD) {
+}
+
} // namespace Maps
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/maps/child.h b/engines/mm/mm1/views/maps/prisoners.h
similarity index 59%
rename from engines/mm/mm1/views/maps/child.h
rename to engines/mm/mm1/views/maps/prisoners.h
index 9c57402e3be..8e1fe3bdf92 100644
--- a/engines/mm/mm1/views/maps/child.h
+++ b/engines/mm/mm1/views/maps/prisoners.h
@@ -19,25 +19,58 @@
*
*/
-#ifndef MM1_VIEWS_MAPS_CHILD_H
-#define MM1_VIEWS_MAPS_CHILD_H
+#ifndef MM1_VIEWS_MAPS_PRISONERS_H
+#define MM1_VIEWS_MAPS_PRISONERS_H
#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/data/character.h"
namespace MM {
namespace MM1 {
namespace Views {
namespace Maps {
-class Child : public TextView {
+class Prisoner : public TextView {
+private:
+ Common::String _line1;
+ byte _flag;
+ Alignment _freeAlignment;
+ Alignment _leaveAlignment;
public:
- Child();
- virtual ~Child() {}
+ Prisoner(const Common::String &name, const Common::String &line1,
+ byte flag, Alignment freeAlignment, Alignment leaveAlignment);
+ virtual ~Prisoner() {}
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
+class ChildPrisoner : public Prisoner {
+public:
+ ChildPrisoner();
+ virtual ~ChildPrisoner() {}
+};
+
+class ManPrisoner : public Prisoner {
+public:
+ ManPrisoner();
+ virtual ~ManPrisoner() {}
+};
+
+class CloakedPrisoner : public Prisoner {
+public:
+ CloakedPrisoner();
+ virtual ~CloakedPrisoner() {
+ }
+};
+
+class DemonPrisoner : public Prisoner {
+public:
+ DemonPrisoner();
+ virtual ~DemonPrisoner() {
+ }
+};
+
} // namespace Maps
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 98ae76db4d4..a4d003f0ae4 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -55,11 +55,11 @@ MODULE_OBJS := \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
mm1/views/maps/chess.o \
- mm1/views/maps/child.o \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
mm1/views/maps/lion.o \
+ mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \
mm1/views/maps/trivia.o \
mm1/views/maps/volcano_god.o \
Commit: 80b9faec1cd20678f3b1c536cacf5d48d2ebbfdb
https://github.com/scummvm/scummvm/commit/80b9faec1cd20678f3b1c536cacf5d48d2ebbfdb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: Most of map 35, Inspectron code in progress
Changed paths:
A engines/mm/mm1/views/maps/inspectron.cpp
A engines/mm/mm1/views/maps/inspectron.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map35.h
engines/mm/mm1/maps/map_desert.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 8e023f56e69..44588866149 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1301,3 +1301,23 @@ maps:
door: "A GOLDEN DOOR REPELS YOU!"
alamar1: "SUSPENDED IN A FORCEFIELD IS THE BODY\nOF A MAN ENCLOSED IN AN IRON SUIT.\nTELEPATHIC COMMUNICATION:""I AM THE TRUE\nKING ALAMAR, IMPRISONED BY A DEMONIC\nALIEN BEING! CONFRONT HIM WITH THIS EYE\nOF GOROS AND YOU SHALL SEE HIS TRUE\nSELF."
alamar2: "THE FATE OF THE REALM IS AT STAKE."""
+
+ map35:
+ exit: "EXIT CASTLE, (Y/N)?"
+ guards: "CASTLE GUARDS EXCLAIM\n""NO MERCHANTS PASS! BEGONE PEASANTS."""
+ quests:
+ 0: "FIND THE ANCIENT RUINS IN THE\nQUIVERING FOREST"
+ 1: "VISIT BLITHES PEAK, AND REPORT"
+ 2: "THE PEOPLE OF THE DESERT HAVE MUCH TO\nTRADE,BRING ME A SAMPLE OF THEIR GOODS"
+ 3: "FIND THE SHRINE OF OKZAR IN THE\nCAVES BELOW DUSK"
+ 4: "FIND THE FABLED FOUNTAIN IN DRAGADUNE"
+ 5: "SOLVE THE RIDDLE OF THE RUBY"
+ 6: "DEFEAT THE STRONGHOLD\nIN THE ENCHANTED FOREST"
+ inspectron1: "LORD INSPECTRON SPEAKS:\n"
+ inspectron2: """YOUR SERVICES ARE NEEDED!"" ACCEPT (Y/N)?"
+ inspectron3: """RETURN NOT UNTIL THY QUEST IS COMPLETE"""
+ inspectron4: """SORRY, BUT SINCE YOU ARE CURRENTLY\nQUESTED, I CAN'T ENGAGE YOUR SERVICES."""
+ inspectron5: "WELL DONE, QUEST COMPLETE! +%d EXP"
+ message: "ETCHED IN SILVER, MESSAGE A READS:\nATIS-19-31UD54AEUPI1"
+ slide: "A SLIDE!"
+ vault: "EMPTY VAULT, ALARM!"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 3602c402da4..1b918957399 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -107,7 +107,11 @@ enum CharFlags5 {
CHARFLAG5_1 = 1,
CHARFLAG5_2 = 2,
CHARFLAG5_4 = 4,
- CHARFLAG5_8 = 8
+ CHARFLAG5_8 = 8,
+ CHARFLAG5_10 = 0x10,
+ CHARFLAG5_20 = 0x20,
+ CHARFLAG5_40 = 0x40,
+ CHARFLAG5_80 = 0x80
};
enum CharFlags7 {
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 92fabf97d45..cac89e6e726 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -34,6 +34,7 @@ namespace MM1 {
enum ItemId {
VELLUM_SCROLL_ID = 231,
RUBY_WHISTLE_ID = 232,
+ MERCHANTS_PASS_ID = 234,
CORAL_KEY_ID = 236,
BRONZE_KEY_ID = 237,
SILVER_KEY_ID = 238,
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 29c5580dca0..b7404b70f9b 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -108,6 +108,10 @@ void Map::updateGame() {
g_events->send("Game", GameMessage("UPDATE"));
}
+void Map::redrawGame() {
+ g_events->findView("Game")->redraw();
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 91d7599e0d2..725f9af4f1b 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -187,6 +187,11 @@ public:
* Updates the game display
*/
static void updateGame();
+
+ /**
+ * Redraw the game display
+ */
+ static void redrawGame();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index e9458c6415d..4f45f5742f0 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -71,7 +71,7 @@ void Map18::special01() {
_data[VAL1] = 0;
} else {
- g_events->findView("Game")->redraw();
+ redrawGame();
send(SoundMessage(
STRING["maps.map18.blackridge_south"],
[](const Common::KeyState &ks) {
@@ -97,7 +97,7 @@ void Map18::special02() {
_data[VAL2] = 0;
} else {
- g_events->findView("Game")->redraw();
+ redrawGame();
send(SoundMessage(
STRING["maps.map18.blackridge_north"],
[](const Common::KeyState &ks) {
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index f246850eb2f..06443cd9b73 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -29,6 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 29
+#define VAL2 47
+
+static const byte MATCH_ITEMS[7] = {
+ 0, 0,241, 0, 0, 0, 0
+};
+static const byte MATCH_FLAGS[7] = {
+ CHARFLAG5_1, CHARFLAG5_2, CHARFLAG5_4, CHARFLAG5_8,
+ CHARFLAG5_10, CHARFLAG5_20, CHARFLAG5_40
+};
+
void Map35::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < 11; ++i) {
@@ -55,27 +66,109 @@ void Map35::special00() {
}
void Map35::special01() {
+ send(SoundMessage(
+ STRING["maps.map35.exit"],
+ []() {
+ g_maps->_mapPos = Common::Point(14, 10);
+ g_maps->changeMap(0xa00, 2);
+ }
+ ));
}
void Map35::special02() {
+ send(SoundMessage(STRING["maps.map35.slide"]));
+ g_maps->_mapPos = Common::Point(14, 9);
+ g_maps->changeMap(0xa00, 2);
}
void Map35::special03() {
+ send(SoundMessage(STRING["maps.map35.message"]));
}
void Map35::special04() {
+ if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
+ send(SoundMessage(STRING["maps.map35.merchants"]));
+ g_maps->_mapPos.y++;
+ updateGame();
+ }
}
void Map35::special05() {
+ updateFlags();
+ warning("TODO: drawMonster");
+ g_events->addView("Inspectron");
}
void Map35::special06() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[8] = 30;
+ g_events->addAction(KEYBIND_SEARCH);
}
void Map35::special07() {
+ send(SoundMessage(STRING["maps.map35.vault"]));
+ _data[VAL1] = 30;
+ _data[VAL2] = 7;
}
void Map35::special09() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[8] = 50;
+ special07();
+}
+
+void Map35::updateFlags() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ int counte = c._equipped.size();
+ int count = counte + c._backpack.size();
+ for (int itemIdx = 0; itemIdx < count; ++itemIdx) {
+ byte itemId = (itemIdx < counte) ?
+ c._equipped[itemIdx]._id : c._backpack[itemIdx - counte]._id;
+
+ // Scan list of items to match against
+ for (int arrIdx = 0; arrIdx < 7; ++arrIdx) {
+ if (itemId == MATCH_ITEMS[arrIdx]) {
+ c._flags[5] |= MATCH_FLAGS[arrIdx];
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Map35::acceptQuest() {
+ Character &leader = g_globals->_party[0];
+ byte flags = leader._flags[8];
+
+ // Find quest that hasn't been done yet
+ int questNum;
+ for (questNum = 8; flags && questNum < 15; ++questNum, flags >>= 1) {
+ if (!(flags & 1))
+ break;
+ }
+ if (questNum == 15) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[8] = CHARFLAG8_80;
+ c._flags[5] = CHARFLAG5_80;
+ }
+ }
+
+ // Assign the quest to all party characters
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = questNum;
+ }
+
+ // Draw the scene
+ g_maps->_mapPos.y++;
+ redrawGame();
+}
+
+bool Map35::matchQuest(Common::String &line) {
+ // TODO
+ return false;
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map35.h b/engines/mm/mm1/maps/map35.h
index 1064706fe39..8eeb634d80c 100644
--- a/engines/mm/mm1/maps/map35.h
+++ b/engines/mm/mm1/maps/map35.h
@@ -40,6 +40,7 @@ private:
void special06();
void special07();
void special09();
+ void updateFlags();
const SpecialFn SPECIAL_FN[11] = {
&Map35::special00,
@@ -61,6 +62,17 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Accepts a quest from Inspectron
+ */
+ void acceptQuest();
+
+ /**
+ * Does a check for the party's current quest is one
+ * of Inspectron's, and if it's complete
+ */
+ bool matchQuest(Common::String &line);
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map_desert.cpp b/engines/mm/mm1/maps/map_desert.cpp
index 7ec410cfc35..91e4c83d7d8 100644
--- a/engines/mm/mm1/maps/map_desert.cpp
+++ b/engines/mm/mm1/maps/map_desert.cpp
@@ -29,8 +29,6 @@ namespace MM1 {
namespace Maps {
void MapDesert::desert() {
- Game::Encounter &enc = g_globals->_encounters;
-
SoundMessage msg;
msg._lines.push_back(Line(0, 1, STRING["maps.desert.its_hot"]));
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index fda980c2dcf..11b38948ef2 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -47,6 +47,7 @@
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
#include "mm/mm1/views/maps/ice_princess.h"
+#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/views/maps/resistances.h"
@@ -96,6 +97,7 @@ private:
Views::Maps::DemonPrisoner _demonPrisoner;
Views::Maps::ManPrisoner _manPrisoner;
Views::Maps::IcePrincess _icePrincess;
+ Views::Maps::Inspectron _inspectron;
Views::Maps::Lion _lion;
Views::Maps::Resistances _resistances;
Views::Maps::Trivia _trivia;
diff --git a/engines/mm/mm1/views/maps/inspectron.cpp b/engines/mm/mm1/views/maps/inspectron.cpp
new file mode 100644
index 00000000000..40e4416f717
--- /dev/null
+++ b/engines/mm/mm1/views/maps/inspectron.cpp
@@ -0,0 +1,97 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/inspectron.h"
+#include "mm/mm1/maps/map35.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define VAL1 123
+#define ANSWER_OFFSET 167
+
+Inspectron::Inspectron() : TextView("Inspectron") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Inspectron::msgFocus(const FocusMessage &msg) {
+ _canAccept = !g_globals->_party[0]._quest;
+ return TextView::msgFocus(msg);
+}
+
+void Inspectron::draw() {
+ MM1::Maps::Map35 &map = *static_cast<MM1::Maps::Map35 *>(g_maps->_currentMap);
+ clearSurface();
+
+ if (_canAccept) {
+ send(SoundMessage(
+ 0, 1, STRING["maps.map35.inspectron1"],
+ 0, 2, STRING["maps.map35.inspectron2"]
+ ));
+ } else {
+ int questNum = g_globals->_party[0]._quest;
+ Common::String line;
+
+ if (questNum < 8 || questNum > 14 || !map.matchQuest(line))
+ line = STRING["maps.map35.inspectron4"];
+
+ g_maps->_mapPos.y++;
+ map.redrawGame();
+
+ clearSurface();
+ send(SoundMessage(
+ 0, 1, STRING["maps.map35.inspectron1"],
+ 0, 2, line
+ ));
+ close();
+ }
+}
+
+bool Inspectron::msgKeypress(const KeypressMessage &msg) {
+ MM1::Maps::Map35 &map = *static_cast<MM1::Maps::Map35 *>(g_maps->_currentMap);
+
+ if (_canAccept) {
+ if (msg.keycode == Common::KEYCODE_y) {
+ map.acceptQuest();
+
+ clearSurface();
+ writeString(0, 1, STRING["maps.map35.inspectron1"]);
+ writeString(0, 2, STRING[Common::String::format(
+ "maps.map35.quests.%d",
+ g_globals->_party[0]._quest)]);
+ close();
+
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ map.redrawGame();
+ }
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/inspectron.h b/engines/mm/mm1/views/maps/inspectron.h
new file mode 100644
index 00000000000..257d863e691
--- /dev/null
+++ b/engines/mm/mm1/views/maps/inspectron.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_INSPECTRON_H
+#define MM1_VIEWS_MAPS_INSPECTRON_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Inspectron : public TextView {
+private:
+ bool _canAccept;
+public:
+ Inspectron();
+ virtual ~Inspectron() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index a4d003f0ae4..f173c5e38cd 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -58,6 +58,7 @@ MODULE_OBJS := \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
+ mm1/views/maps/inspectron.o \
mm1/views/maps/lion.o \
mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \
Commit: ee4a7759c882ce9b364a321b0d9ed4974bc6e857
https://github.com/scummvm/scummvm/commit/ee4a7759c882ce9b364a321b0d9ed4974bc6e857
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: Remainder of map 35's Inspectron code
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map35.h
engines/mm/mm1/views/maps/inspectron.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 44588866149..c051a323be4 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1317,7 +1317,7 @@ maps:
inspectron2: """YOUR SERVICES ARE NEEDED!"" ACCEPT (Y/N)?"
inspectron3: """RETURN NOT UNTIL THY QUEST IS COMPLETE"""
inspectron4: """SORRY, BUT SINCE YOU ARE CURRENTLY\nQUESTED, I CAN'T ENGAGE YOUR SERVICES."""
- inspectron5: "WELL DONE, QUEST COMPLETE! +%d EXP"
+ inspectron5: "WELL DONE, QUEST COMPLETE! +%u EXP"
message: "ETCHED IN SILVER, MESSAGE A READS:\nATIS-19-31UD54AEUPI1"
slide: "A SLIDE!"
vault: "EMPTY VAULT, ALARM!"
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 06443cd9b73..c1ad3197a82 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -35,9 +35,11 @@ namespace Maps {
static const byte MATCH_ITEMS[7] = {
0, 0,241, 0, 0, 0, 0
};
-static const byte MATCH_FLAGS[7] = {
- CHARFLAG5_1, CHARFLAG5_2, CHARFLAG5_4, CHARFLAG5_8,
- CHARFLAG5_10, CHARFLAG5_20, CHARFLAG5_40
+static const byte MATCH_FLAGS[8] = {
+ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80
+};
+static const uint16 QUEST_EXPERIENCE[7] = {
+ 1000, 2000, 3000, 4000, 6000, 8000, 10000
};
void Map35::special() {
@@ -166,9 +168,26 @@ void Map35::acceptQuest() {
redrawGame();
}
-bool Map35::matchQuest(Common::String &line) {
- // TODO
- return false;
+Common::String Map35::checkQuestComplete() {
+ Character &leader = g_globals->_party[0];
+ int qIndex = leader._quest - 7;
+
+ if (leader._flags[5] & MATCH_FLAGS[qIndex]) {
+ // The quest was complete
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = 0;
+ c._flags[8] |= MATCH_FLAGS[qIndex];
+ c._exp += QUEST_EXPERIENCE[qIndex];
+ }
+
+ return Common::String::format(
+ STRING["maps.map35.inspectron5"].c_str(),
+ QUEST_EXPERIENCE[qIndex]);
+ } else {
+ // The quest isn't yet complete
+ return STRING["maps.map35.inspectron3"];
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map35.h b/engines/mm/mm1/maps/map35.h
index 8eeb634d80c..2508adbebd6 100644
--- a/engines/mm/mm1/maps/map35.h
+++ b/engines/mm/mm1/maps/map35.h
@@ -69,10 +69,10 @@ public:
void acceptQuest();
/**
- * Does a check for the party's current quest is one
- * of Inspectron's, and if it's complete
+ * Does a check for whether Inspectron's current quest
+ * is complete or not
*/
- bool matchQuest(Common::String &line);
+ Common::String checkQuestComplete();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/inspectron.cpp b/engines/mm/mm1/views/maps/inspectron.cpp
index 40e4416f717..5d969451527 100644
--- a/engines/mm/mm1/views/maps/inspectron.cpp
+++ b/engines/mm/mm1/views/maps/inspectron.cpp
@@ -36,7 +36,8 @@ Inspectron::Inspectron() : TextView("Inspectron") {
}
bool Inspectron::msgFocus(const FocusMessage &msg) {
- _canAccept = !g_globals->_party[0]._quest;
+ g_globals->_currCharacter = &g_globals->_party[0];
+ _canAccept = !g_globals->_currCharacter->_quest;
return TextView::msgFocus(msg);
}
@@ -53,7 +54,9 @@ void Inspectron::draw() {
int questNum = g_globals->_party[0]._quest;
Common::String line;
- if (questNum < 8 || questNum > 14 || !map.matchQuest(line))
+ if (questNum >= 8 || questNum <= 14)
+ line = map.checkQuestComplete();
+ else
line = STRING["maps.map35.inspectron4"];
g_maps->_mapPos.y++;
Commit: 9a20265a5fe2d2a254c62a4020177799586dec30
https://github.com/scummvm/scummvm/commit/9a20265a5fe2d2a254c62a4020177799586dec30
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: In progress map 36
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map36.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c051a323be4..903c95778e1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1321,3 +1321,24 @@ maps:
message: "ETCHED IN SILVER, MESSAGE A READS:\nATIS-19-31UD54AEUPI1"
slide: "A SLIDE!"
vault: "EMPTY VAULT, ALARM!"
+
+ map36:
+ exit: "EXIT CASTLE, (Y/N)?"
+ slide: "SLIDE!"
+ pit: "THE PIT OF PERIL..."
+ vault: "EMPTY VAULT, ALARM!"
+ ingredients:
+ 0: "GARLIC"
+ 1: "WOLFSBANE"
+ 2: "BELLADONNA"
+ 3: "THE HEAD OF A MEDUSA"
+ 4: "AN EYE OF A WYVERN"
+ 5: "A DRAGONS TOOTH"
+ 6: "THE RING OF OKIRM"
+ hacker1: "LORD HACKER SPEAKS:\n"
+ hacker2: """YOUR SERVICES ARE NEEDED!""ACCEPT (Y/N)?"
+ hacker3: "BRING ME "
+ hacker4: """SORRY, YOU'RE ALREADY QUESTED."""
+ hacker5: """RETURN NOT UNTIL THY QUEST IS COMPLETE""\n(LEADER SHOULD PRESENT ITEMS)"
+ hacker6: "MY BREW IS COMPLETE, GUARDS TAKE THEIR\nITEMS AND SEND THEM TO THE PIT!"
+ message: "ETCHED IN SILVER, MESSAGE C READS:\nIACI1;-2;0NU--G,NOT2"
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index 49caf86a357..cded393ebe6 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map36::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 15; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[66 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,49 @@ void Map36::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map36::special00() {
+ g_events->addView("CloakedPrisoner");
+}
+
+void Map36::special01() {
+ send(SoundMessage(
+ STRING["maps.map36.exit"],
+ []() {
+ g_maps->_mapPos = Common::Point(11, 2);
+ g_maps->changeMap(0xa00, 2);
+ }
+ ));
+}
+
+void Map36::special02() {
+ send(SoundMessage(STRING["maps.map36.slide"]));
+ g_maps->_mapPos = Common::Point(12, 2);
+ g_maps->changeMap(0xa00, 2);
+}
+
+void Map36::special03() {
+ send(SoundMessage(STRING["maps.map36.message"]));
+}
+
+void Map36::special04() {
+}
+
+void Map36::special05() {
+}
+
+void Map36::special06() {
+}
+
+void Map36::special07() {
+}
+
+void Map36::special11() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map36.h b/engines/mm/mm1/maps/map36.h
index 1c37a2a0241..2d364768bf0 100644
--- a/engines/mm/mm1/maps/map36.h
+++ b/engines/mm/mm1/maps/map36.h
@@ -32,9 +32,31 @@ class Map36 : public Map {
typedef void (Map36:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special11();
- const SpecialFn SPECIAL_FN[1] = {
- &Map36::special00
+ const SpecialFn SPECIAL_FN[15] = {
+ &Map36::special00,
+ &Map36::special01,
+ &Map36::special02,
+ &Map36::special03,
+ &Map36::special04,
+ &Map36::special05,
+ &Map36::special06,
+ &Map36::special07,
+ &Map36::special07,
+ &Map36::special07,
+ &Map36::special07,
+ &Map36::special11,
+ &Map36::special11,
+ &Map36::special11,
+ &Map36::special11
};
public:
Map36() : Map(36, "blackrs", 0x508) {}
Commit: 985b617945a1d9986d21f7b23700071a77fb09e7
https://github.com/scummvm/scummvm/commit/985b617945a1d9986d21f7b23700071a77fb09e7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:26+01:00
Commit Message:
MM: MM1: Added map 36
Changed paths:
A engines/mm/mm1/views/maps/hacker.cpp
A engines/mm/mm1/views/maps/hacker.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map36.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 903c95778e1..f8d74b11313 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1324,6 +1324,7 @@ maps:
map36:
exit: "EXIT CASTLE, (Y/N)?"
+ begone: "CASTLE GUARDS EXCLAIM,""BEGONE PEASANTS!"""
slide: "SLIDE!"
pit: "THE PIT OF PERIL..."
vault: "EMPTY VAULT, ALARM!"
@@ -1340,5 +1341,6 @@ maps:
hacker3: "BRING ME "
hacker4: """SORRY, YOU'RE ALREADY QUESTED."""
hacker5: """RETURN NOT UNTIL THY QUEST IS COMPLETE""\n(LEADER SHOULD PRESENT ITEMS)"
- hacker6: "MY BREW IS COMPLETE, GUARDS TAKE THEIR\nITEMS AND SEND THEM TO THE PIT!"
+ hacker6: "WELL DONE, QUEST COMPLETE! +%u EXP"
+ hacker7: "MY BREW IS COMPLETE, GUARDS TAKE THEIR\nITEMS AND SEND THEM TO THE PIT!"
message: "ETCHED IN SILVER, MESSAGE C READS:\nIACI1;-2;0NU--G,NOT2"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 1b918957399..a10676de666 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -114,6 +114,17 @@ enum CharFlags5 {
CHARFLAG5_80 = 0x80
};
+enum CharFlags6 {
+ CHARFLAG6_1 = 1,
+ CHARFLAG6_2 = 2,
+ CHARFLAG6_4 = 4,
+ CHARFLAG6_8 = 8,
+ CHARFLAG6_10 = 0x10,
+ CHARFLAG6_20 = 0x20,
+ CHARFLAG6_40 = 0x40,
+ CHARFLAG6_80 = 0x80
+};
+
enum CharFlags7 {
CHARFLAG7_1 = 1,
CHARFLAG7_2 = 2,
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index cac89e6e726..6a5bf97d9dd 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -32,6 +32,9 @@ namespace MM1 {
#define TREASURE_COUNT 9
enum ItemId {
+ GARLIC_ID = 175,
+ WOLFSBANE_ID = 176,
+ BELLADONNA_ID = 177,
VELLUM_SCROLL_ID = 231,
RUBY_WHISTLE_ID = 232,
MERCHANTS_PASS_ID = 234,
@@ -42,6 +45,10 @@ enum ItemId {
DIAMOND_KEY_ID = 240,
CACTUS_NECTAR_ID = 241,
MAP_OF_DESERT_ID = 242,
+ DRAGONS_TOOTH_ID = 244,
+ WYVERN_EYE_ID = 245,
+ MEDUSA_HEAD_ID = 246,
+ RING_OF_OKRIM_ID = 247,
B_QUEEN_IDOL_ID = 248,
W_QUEEN_IDOL_ID = 249,
PIRATES_MAP_A_ID = 250,
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index c1ad3197a82..7cd7dae7158 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -172,7 +172,7 @@ Common::String Map35::checkQuestComplete() {
Character &leader = g_globals->_party[0];
int qIndex = leader._quest - 7;
- if (leader._flags[5] & MATCH_FLAGS[qIndex]) {
+ if (leader._flags[5] & MATCH_FLAGS[qIndex] & 0x7f) {
// The quest was complete
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index cded393ebe6..b915b7ef55a 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -29,6 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+static const byte MATCH_ITEMS[7] = {
+ GARLIC_ID, WOLFSBANE_ID, BELLADONNA_ID, MEDUSA_HEAD_ID,
+ WYVERN_EYE_ID, DRAGONS_TOOTH_ID, RING_OF_OKRIM_ID
+};
+static const byte MATCH_FLAGS[8] = {
+ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80
+};
+static const uint16 QUEST_EXPERIENCE[7] = {
+ 1000, 2000, 3000, 4000, 6000, 8000, 10000
+};
+
void Map36::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < 15; ++i) {
@@ -74,18 +85,123 @@ void Map36::special03() {
}
void Map36::special04() {
+ if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
+ send(SoundMessage(STRING["maps.map36.begone"]));
+ g_maps->_mapPos.x--;
+ updateGame();
+ }
}
void Map36::special05() {
+ updateFlags();
+ warning("TODO: drawMonster");
+ g_events->addView("Hacker");
}
void Map36::special06() {
+ send(SoundMessage(STRING["maps.map36.pit"]));
+ g_maps->_mapPos = Common::Point(7, 4);
+ g_maps->changeMap(0x705, 3);
}
void Map36::special07() {
+ send(SoundMessage(STRING["maps.map36.vault"]));
+ _data[MAP_47] = 7;
+ _data[MAP_29] = 30;
+ for (int i = 0; i < 3; ++i)
+ Sound::sound(SOUND_2);
}
void Map36::special11() {
+ g_globals->_treasure[8] = 30;
+ special07();
+}
+
+void Map36::updateFlags() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ int counte = c._equipped.size();
+ int count = counte + c._backpack.size();
+ for (int itemIdx = 0; itemIdx < count; ++itemIdx) {
+ byte itemId = (itemIdx < counte) ?
+ c._equipped[itemIdx]._id : c._backpack[itemIdx - counte]._id;
+
+ // Scan list of items to match against
+ for (int arrIdx = 0; arrIdx < 7; ++arrIdx) {
+ if (itemId == MATCH_ITEMS[arrIdx]) {
+ c._flags[6] |= MATCH_FLAGS[arrIdx];
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Map36::acceptQuest() {
+ Character &leader = g_globals->_party[0];
+ byte flags = leader._flags[8];
+
+ // Find quest that hasn't been done yet
+ int questNum;
+ for (questNum = 8; flags && questNum < 15; ++questNum, flags >>= 1) {
+ if (!(flags & 1))
+ break;
+ }
+ if (questNum == 15) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[8] = CHARFLAG8_80;
+ c._flags[5] = CHARFLAG5_80;
+ }
+ }
+
+ // Assign the quest to all party characters
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = questNum;
+ }
+
+ // Draw the scene
+ g_maps->_mapPos.y++;
+ redrawGame();
+}
+
+Common::String Map36::checkQuestComplete() {
+ Character &leader = g_globals->_party[0];
+ int qIndex = leader._quest - 14;
+
+ if (leader._flags[6] & MATCH_FLAGS[qIndex] & 0x7f) {
+ // The quest was complete
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = 0;
+ c._flags[9] |= MATCH_FLAGS[qIndex];
+ c._exp += QUEST_EXPERIENCE[qIndex];
+ }
+
+ return Common::String::format(
+ STRING["maps.map36.inspectron6"].c_str(),
+ QUEST_EXPERIENCE[qIndex]);
+ } else {
+ // The quest isn't yet complete
+ return STRING["maps.map36.hacker5"];
+ }
+}
+
+void Map36::brewComplete() {
+ // Nuke the entire party's backpack contents
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[9] = CHARFLAG9_80;
+ c._flags[6] = CHARFLAG6_80;
+
+ c._backpack.clear();
+ }
+
+ send(SoundMessage(STRING["maps.map36.hacker6"]));
+ g_maps->_mapPos = Common::Point(12, 5);
+ g_maps->_mapPos.x--;
+ redrawGame();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map36.h b/engines/mm/mm1/maps/map36.h
index 2d364768bf0..ba5689723e2 100644
--- a/engines/mm/mm1/maps/map36.h
+++ b/engines/mm/mm1/maps/map36.h
@@ -40,6 +40,8 @@ private:
void special06();
void special07();
void special11();
+ void updateFlags();
+ void brewComplete();
const SpecialFn SPECIAL_FN[15] = {
&Map36::special00,
@@ -65,6 +67,17 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Accepts a quest from Inspectron
+ */
+ void acceptQuest();
+
+ /**
+ * Does a check for whether Inspectron's current quest
+ * is complete or not
+ */
+ Common::String checkQuestComplete();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/hacker.cpp b/engines/mm/mm1/views/maps/hacker.cpp
new file mode 100644
index 00000000000..41be8170dfc
--- /dev/null
+++ b/engines/mm/mm1/views/maps/hacker.cpp
@@ -0,0 +1,97 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/hacker.h"
+#include "mm/mm1/maps/map36.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+Hacker::Hacker() : TextView("Hacker") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Hacker::msgFocus(const FocusMessage &msg) {
+ g_globals->_currCharacter = &g_globals->_party[0];
+ _canAccept = !g_globals->_currCharacter->_quest;
+ return TextView::msgFocus(msg);
+}
+
+void Hacker::draw() {
+ MM1::Maps::Map36 &map = *static_cast<MM1::Maps::Map36 *>(g_maps->_currentMap);
+ clearSurface();
+
+ if (_canAccept) {
+ send(SoundMessage(
+ 0, 1, STRING["maps.map36.hacker1"],
+ 0, 2, STRING["maps.map36.hacker2"]
+ ));
+ } else {
+ int questNum = g_globals->_party[0]._quest;
+ Common::String line;
+
+ if (questNum >= 15 || questNum <= 21)
+ line = map.checkQuestComplete();
+ else
+ line = STRING["maps.map36.hacker4"];
+
+ g_maps->_mapPos.x--;
+ map.redrawGame();
+
+ clearSurface();
+ send(SoundMessage(
+ 0, 1, STRING["maps.map36.hacker1"],
+ 0, 2, line
+ ));
+ close();
+ }
+}
+
+bool Hacker::msgKeypress(const KeypressMessage &msg) {
+ MM1::Maps::Map36 &map = *static_cast<MM1::Maps::Map36 *>(g_maps->_currentMap);
+
+ if (_canAccept) {
+ if (msg.keycode == Common::KEYCODE_y) {
+ map.acceptQuest();
+
+ clearSurface();
+ writeString(0, 1, STRING["maps.map36.hacker1"]);
+ writeString(0, 2, STRING[Common::String::format(
+ "maps.map36.ingredients.%d",
+ g_globals->_party[0]._quest)]);
+ close();
+
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ map.redrawGame();
+ }
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/hacker.h b/engines/mm/mm1/views/maps/hacker.h
new file mode 100644
index 00000000000..020242a7364
--- /dev/null
+++ b/engines/mm/mm1/views/maps/hacker.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_HACKER_H
+#define MM1_VIEWS_MAPS_HACKER_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Hacker : public TextView {
+private:
+ bool _canAccept;
+public:
+ Hacker();
+ virtual ~Hacker() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index f173c5e38cd..d221c27415e 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -57,6 +57,7 @@ MODULE_OBJS := \
mm1/views/maps/chess.o \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
+ mm1/views/maps/hacker.o \
mm1/views/maps/ice_princess.o \
mm1/views/maps/inspectron.o \
mm1/views/maps/lion.o \
Commit: b88d75d26b540969a5c54d47a5e11baa45aacc28
https://github.com/scummvm/scummvm/commit/b88d75d26b540969a5c54d47a5e11baa45aacc28
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: Implement monster/figure drawing for maps 35 & 36
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 85ba92f3002..bed0c027b03 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -236,6 +236,7 @@ public:
MESSAGE(Game);
MESSAGE(Info);
MESSAGE(Value);
+ MESSAGE(DrawMonster);
#undef MESSAGE
};
@@ -266,6 +267,7 @@ protected:
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
+ MESSAGE(DrawMonster);
#undef MESSAGE
public:
Events(bool enhancedMode);
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 7cd7dae7158..6794b6bf5fc 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -97,7 +97,7 @@ void Map35::special04() {
void Map35::special05() {
updateFlags();
- warning("TODO: drawMonster");
+ send("GameView", DrawMonsterMessage(7));
g_events->addView("Inspectron");
}
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index b915b7ef55a..5e51e466448 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -94,7 +94,7 @@ void Map36::special04() {
void Map36::special05() {
updateFlags();
- warning("TODO: drawMonster");
+ send("GameView", DrawMonsterMessage(7));
g_events->addView("Hacker");
}
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 16dd7df46aa..61cad4d8b48 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -172,6 +172,14 @@ struct ValueMessage : public Message {
_value(value) {}
};
+struct DrawMonsterMessage : public Message {
+ int _monsterNum;
+
+ DrawMonsterMessage() : Message(), _monsterNum(0) {}
+ explicit DrawMonsterMessage(int monsterNum) : Message(),
+ _monsterNum(monsterNum) {}
+};
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index eea13a90bc0..45549efcf39 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -123,7 +123,7 @@ void Encounter::draw() {
if (_mode != ALERT) {
// Display the monster
- drawMonster(enc._monsterImgNum);
+ msgDrawMonster(DrawMonsterMessage(enc._monsterImgNum));
// Write the monster list
for (uint i = 0; i < enc._monsterList.size(); ++i) {
@@ -145,12 +145,6 @@ void Encounter::draw() {
}
}
-void Encounter::drawMonster(int monsterNum) {
- Graphics::ManagedSurface img =
- g_globals->_monsters.getMonsterImage(monsterNum);
- getSurface().blitFrom(img, Common::Point(64, 16));
-}
-
void Encounter::timeout() {
const Game::Encounter &enc = g_globals->_encounters;
const Maps::Map &map = *g_maps->_currentMap;
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index d89027923ea..d205c3d148e 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -42,11 +42,6 @@ private:
BribeType _bribeType = BRIBE_GOLD;
Common::String _bribeTypeStr;
- /**
- * Draws a monster
- */
- void drawMonster(int monsterNum);
-
/**
* Handles the end of the encounter
*/
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 7882a7b9532..21b73fc60c1 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -139,6 +139,13 @@ void TextView::timeout() {
redraw();
}
+bool TextView::msgDrawMonster(const DrawMonsterMessage &msg) {
+ Graphics::ManagedSurface img =
+ g_globals->_monsters.getMonsterImage(msg._monsterNum);
+ getSurface().blitFrom(img, Common::Point(64, 16));
+ return true;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 4374bc81a0c..27596cd7f40 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -101,6 +101,8 @@ public:
TextView(const Common::String &name);
TextView(const Common::String &name, UIElement *owner);
virtual ~TextView() {}
+
+ bool msgDrawMonster(const DrawMonsterMessage &msg) override;
};
} // namespace Views
Commit: 60512d223ad16471f16551803dc34782e8f42041
https://github.com/scummvm/scummvm/commit/60512d223ad16471f16551803dc34782e8f42041
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: Added map 37
Changed paths:
A engines/mm/mm1/views/maps/ghost.cpp
A engines/mm/mm1/views/maps/ghost.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map37.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index f8d74b11313..f7bef4dcc45 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1344,3 +1344,12 @@ maps:
hacker6: "WELL DONE, QUEST COMPLETE! +%u EXP"
hacker7: "MY BREW IS COMPLETE, GUARDS TAKE THEIR\nITEMS AND SEND THEM TO THE PIT!"
message: "ETCHED IN SILVER, MESSAGE C READS:\nIACI1;-2;0NU--G,NOT2"
+
+ map37:
+ message1: "ETCHED IN GOLD, MESSAGE 1 READS:\nCOMPLETION-MUST-EACH-KINGS-OF-ASTRAL-\nWITH-9TH-SANCTUM-AND-WONDROUS"
+ okrim1: "A GHOSTLIKE FIGURE RISES FROM THE BODY\nOF OKRIM AND SPEAKS,""IN EXCHANGE FOR\nMY RING, FORFEIT A LIFE, ACCEPT (Y/N)?"""
+ okrim2: """MAY THE SHADOW OF DEATH GREET YOU\nWITH OPEN ARMS!"""
+ archway: "A GEM ENCRUSTED ARCHWAY READS:\nLAIR OF THE OMNIPOTENT WIZARD OKRIM"
+ opening: "AN OPENING ABOVE LEADS OUTSIDE,\nCLIMB OUT (Y/N)?"
+ spins: "THE FLOOR SPINS!"
+ wall: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index 59de3898795..e6082abecad 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 232
+
void Map37::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 20; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[71 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,142 @@ void Map37::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ // TODO: figure out unknown method that determines whether
+ // the floor spins or not
+ if (true) {
+ send(SoundMessage(STRING["maps.map37.spins"]));
+ g_events->addAction(KEYBIND_TURN_LEFT);
+ }
}
void Map37::special00() {
+ send(SoundMessage(STRING["maps.map37.message1"]));
+}
+
+void Map37::special01() {
+ if (_data[VAL1]) {
+ none160();
+ } else {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._flags[5] |= CHARFLAG5_1;
+ }
+
+ send(SoundMessage(
+ STRING["maps.map37.opening"],
+ []() {
+ g_maps->_mapPos = Common::Point(13, 5);
+ g_maps->changeMap(0xa00, 2);
+ }
+ ));
+ }
+}
+
+void Map37::special02() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->_mapPos.x = 15;
+ g_maps->changeMap(0x703, 3);
+ }
+ ));
+}
+
+void Map37::special03() {
+ special02();
+}
+
+void Map37::special04() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ if (_data[VAL1]) {
+ g_events->addView("Ghost");
+
+ } else {
+ _data[VAL1]++;
+
+ enc.clearMonsters();
+ enc.addMonster(19, 12);
+ for (int i = 1; i < 4; ++i)
+ enc.addMonster(14, 8);
+ enc.addMonster(16, 12);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
+}
+
+void Map37::special05() {
+ encounter(&_data[553], &_data[562]);
+}
+
+void Map37::special06() {
+ encounter(&_data[571], &_data[586]);
+}
+
+void Map37::special07() {
+ encounter(&_data[601], &_data[615]);
+}
+
+void Map37::special08() {
+ encounter(&_data[629], &_data[641]);
+}
+
+void Map37::special09() {
+ encounter(&_data[653], &_data[662]);
+}
+
+void Map37::special10() {
+ encounter(&_data[671], &_data[681]);
+}
+
+void Map37::special11() {
+ encounter(&_data[691], &_data[699]);
+}
+
+void Map37::special12() {
+ encounter(&_data[707], &_data[714]);
+}
+
+void Map37::special13() {
+ encounter(&_data[721], &_data[730]);
+}
+
+void Map37::special14() {
+ encounter(&_data[739], &_data[752]);
+}
+
+void Map37::special15() {
+ send(SoundMessage(STRING["maps.map37.wall"]));
+
+ if (!g_globals->_party.hasItem(B_QUEEN_IDOL_ID)) {
+ g_globals->_treasure[5] = B_QUEEN_IDOL_ID;
+ }
+}
+
+void Map37::special16() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[2] = 8;
+ g_globals->_treasure[8] = 100;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map37::special19() {
+ send(SoundMessage(STRING["maps.map37.archway"]));
+}
+
+void Map37::encounter(const byte *id1, const byte *id2) {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+
+ enc.clearMonsters();
+ for (int i = 0; i < 14 && *id1; ++i, ++id1, ++id2)
+ enc.addMonster(*id1, *id2);
+
+ enc._flag = true;
+ enc._levelIndex = 64;
+ enc.execute();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map37.h b/engines/mm/mm1/maps/map37.h
index 46bd5cf8ba7..bd8df14fba3 100644
--- a/engines/mm/mm1/maps/map37.h
+++ b/engines/mm/mm1/maps/map37.h
@@ -32,9 +32,46 @@ class Map37 : public Map {
typedef void (Map37:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special19();
+ void encounter(const byte *id1, const byte *id2);
- const SpecialFn SPECIAL_FN[1] = {
- &Map37::special00
+ const SpecialFn SPECIAL_FN[20] = {
+ &Map37::special00,
+ &Map37::special01,
+ &Map37::special02,
+ &Map37::special03,
+ &Map37::special04,
+ &Map37::special05,
+ &Map37::special06,
+ &Map37::special07,
+ &Map37::special08,
+ &Map37::special09,
+ &Map37::special10,
+ &Map37::special11,
+ &Map37::special12,
+ &Map37::special13,
+ &Map37::special14,
+ &Map37::special15,
+ &Map37::special16,
+ &Map37::special16,
+ &Map37::special16,
+ &Map37::special19
};
public:
Map37() : Map(37, "qvl1", 0xF03) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 11b38948ef2..1b2504a48ed 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -46,6 +46,8 @@
#include "mm/mm1/views/maps/alien.h"
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
+#include "mm/mm1/views/maps/ghost.h"
+#include "mm/mm1/views/maps/giant.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/views/maps/lion.h"
@@ -96,6 +98,8 @@ private:
Views::Maps::CloakedPrisoner _cloakedPrisoner;
Views::Maps::DemonPrisoner _demonPrisoner;
Views::Maps::ManPrisoner _manPrisoner;
+ Views::Maps::Ghost _ghost;
+ Views::Maps::Giant _giant;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Inspectron _inspectron;
Views::Maps::Lion _lion;
diff --git a/engines/mm/mm1/views/maps/ghost.cpp b/engines/mm/mm1/views/maps/ghost.cpp
new file mode 100644
index 00000000000..473f24eb879
--- /dev/null
+++ b/engines/mm/mm1/views/maps/ghost.cpp
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/ghost.h"
+#include "mm/mm1/maps/map37.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define VAL1 123
+#define ANSWER_OFFSET 167
+
+Ghost::Ghost() : TextView("Ghost") {
+ _bounds = getLineBounds(20, 24);
+}
+
+void Ghost::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map37.okram1"]);
+}
+
+bool Ghost::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_y || msg.keycode == Common::KEYCODE_n) {
+ MM1::Maps::Map37 &map = *static_cast<MM1::Maps::Map37 *>(g_maps->_currentMap);
+
+ if (msg.keycode == Common::KEYCODE_y) {
+ g_globals->_party[0]._condition = ERADICATED;
+ } else {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map37.okram2"]);
+
+ map[MM1::Maps::MAP_29] = 32;
+ map[MM1::Maps::MAP_47] = 8;
+ }
+
+ close();
+ g_globals->_treasure[5] = RING_OF_OKRIM_ID;
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/ghost.h b/engines/mm/mm1/views/maps/ghost.h
new file mode 100644
index 00000000000..23f17cdaef6
--- /dev/null
+++ b/engines/mm/mm1/views/maps/ghost.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_GHOST_H
+#define MM1_VIEWS_MAPS_GHOST_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Ghost : public TextView {
+public:
+ Ghost();
+ virtual ~Ghost() {}
+
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index d221c27415e..f30a4acdf83 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -55,6 +55,7 @@ MODULE_OBJS := \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
mm1/views/maps/chess.o \
+ mm1/views/maps/ghost.o \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/hacker.o \
Commit: 1dd7315fa4e8d2ba69d854540fec4680f477ef3d
https://github.com/scummvm/scummvm/commit/1dd7315fa4e8d2ba69d854540fec4680f477ef3d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: In progress map 38
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map38.cpp
engines/mm/mm1/maps/map38.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index f7bef4dcc45..2c8892b690a 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1353,3 +1353,13 @@ maps:
opening: "AN OPENING ABOVE LEADS OUTSIDE,\nCLIMB OUT (Y/N)?"
spins: "THE FLOOR SPINS!"
wall: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+
+ map38:
+ message4: "ETCHED IN GOLD, MESSAGE 4 READS:'\nOF-BE-HAS-TRUE-KNOWLEDGE-PLANE-A-LEVEL-'\nTO-REALITY-IT"
+ banner: "A BANNER READS:\nTHE LABYRINTH OF LAZZERUTH...\nFEW HAVE ENTERED, NONE HAVE RETURNED!"
+ face1: "INSET IN THE WALL, A STONE FACE\nYELLS: ""MY BRAIN HURTS!"""
+ face2: "INSET IN THE WALL, A STONE FACE\nSPEAKS: ""I WOULD PAY HIGHLY FOR A GREEN\nHANDLED, PEARL ENCRUSTED ABELNUSKI."""
+ face3: "INSET IN THE WALL, A STONE FACE\nSPEAKS: ""I SEE ALL, HEAR ALL,\nKNOW NOTHING..."""
+ face4: "INSET IN THE WALL, A STONE FACE\nPROCLAIMS: ""OKRIM IS WATCHING.\nHE STUDIES YOUR WEAKNESSES!"""
+ wall: THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+ ringing: "A STRANGE RINGING SOUND STARTLES\nTHE PARTY. YOU ARE TELEPORTED!"
diff --git a/engines/mm/mm1/maps/map38.cpp b/engines/mm/mm1/maps/map38.cpp
index 38144473fd6..a4fd59f2cab 100644
--- a/engines/mm/mm1/maps/map38.cpp
+++ b/engines/mm/mm1/maps/map38.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map38::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 19; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[70 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,69 @@ void Map38::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ send(SoundMessage(STRING["maps.map38.ringing"]));
+ g_maps->_mapPos = Common::Point(getRandomNumber(16) - 1,
+ getRandomNumber(16) - 1);
+ updateGame();
}
void Map38::special00() {
+ send(SoundMessage(STRING["maps.map38.message4"]));
+}
+
+void Map38::special01() {
+}
+
+void Map38::special02() {
+}
+
+void Map38::special03() {
+}
+
+void Map38::special04() {
+}
+
+void Map38::special05() {
+}
+
+void Map38::special06() {
+}
+
+void Map38::special07() {
+}
+
+void Map38::special08() {
+}
+
+void Map38::special09() {
+}
+
+void Map38::special10() {
+}
+
+void Map38::special11() {
+}
+
+void Map38::special12() {
+}
+
+void Map38::special13() {
+}
+
+void Map38::special14() {
+}
+
+void Map38::special15() {
+}
+
+void Map38::special16() {
+}
+
+void Map38::special17() {
+}
+
+void Map38::special18() {
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map38.h b/engines/mm/mm1/maps/map38.h
index dc672b61448..eaa0c851699 100644
--- a/engines/mm/mm1/maps/map38.h
+++ b/engines/mm/mm1/maps/map38.h
@@ -32,9 +32,45 @@ class Map38 : public Map {
typedef void (Map38:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special17();
+ void special18();
- const SpecialFn SPECIAL_FN[1] = {
- &Map38::special00
+ const SpecialFn SPECIAL_FN[19] = {
+ &Map38::special00,
+ &Map38::special01,
+ &Map38::special02,
+ &Map38::special03,
+ &Map38::special04,
+ &Map38::special05,
+ &Map38::special06,
+ &Map38::special07,
+ &Map38::special08,
+ &Map38::special09,
+ &Map38::special10,
+ &Map38::special11,
+ &Map38::special12,
+ &Map38::special13,
+ &Map38::special14,
+ &Map38::special15,
+ &Map38::special16,
+ &Map38::special17,
+ &Map38::special18
};
public:
Map38() : Map(38, "qvl2", 0x703) {}
Commit: 3b9adfe37b6d5592eb954e539638344019ae4063
https://github.com/scummvm/scummvm/commit/3b9adfe37b6d5592eb954e539638344019ae4063
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: Add missing code to map 24
Changed paths:
engines/mm/mm1/maps/map24.cpp
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index 75b3732aa33..d4e87c7fc02 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -66,23 +66,35 @@ void Map24::special01() {
}
void Map24::special02() {
- send(SoundMessage(
- STRING["maps.map24.lair"],
- []() {
- Game::Encounter &enc = g_globals->_encounters;
- int monsterCount = getRandomNumber(4) + 3;
-
- enc.clearMonsters();
- enc.addMonster(6, 8);
- for (int i = 1; i < monsterCount; ++i)
- enc.addMonster(14, 7);
-
- enc._flag = true;
- enc._encounterType = Game::FORCE_SURPRISED;
- enc._levelIndex = 40;
- enc.execute();
- }
- ));
+ if (_data[VAL1]) {
+ send(SoundMessage(
+ STRING["maps.map24.wyvern_eye"],
+ []() {
+ Map24 &map = *static_cast<Map24 *>(g_maps->_currentMap);
+ map.addItem(WYVERN_EYE_ID);
+ }
+ ));
+ } else {
+ send(SoundMessage(
+ STRING["maps.map24.lair"],
+ []() {
+ Map24 &map = *static_cast<Map24 *>(g_maps->_currentMap);
+ Game::Encounter &enc = g_globals->_encounters;
+ map[VAL1]++;
+
+ int monsterCount = getRandomNumber(4) + 3;
+ enc.clearMonsters();
+ enc.addMonster(6, 8);
+ for (int i = 1; i < monsterCount; ++i)
+ enc.addMonster(14, 7);
+
+ enc._flag = true;
+ enc._encounterType = Game::FORCE_SURPRISED;
+ enc._levelIndex = 40;
+ enc.execute();
+ }
+ ));
+ }
}
void Map24::special03() {
Commit: 86a2c0b7414faad00568b43d55db7d3bbe82e0c5
https://github.com/scummvm/scummvm/commit/86a2c0b7414faad00568b43d55db7d3bbe82e0c5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: Remainder of map 38
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map38.cpp
engines/mm/mm1/maps/map38.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 2c8892b690a..85e761ed920 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1171,7 +1171,7 @@ maps:
map24:
wyverns: "WYVERNS ATTACK FROM ABOVE!"
- wyvern_eys: "ONE OF THE WYVERN'S EYES BEGINS TO GLOW!TAKE IT (Y/N)?"
+ wyvern_eye: "ONE OF THE WYVERN'S EYES BEGINS TO GLOW!TAKE IT (Y/N)?"
roadsign: "ROADSIGN: SORPIGAL N.22, W.2, N.2"
kilburn: "THE EXILED LORD KILBURN SPEAKS:\n""TAKE THIS MAP AND EXPLORE THE DESERT.\nREPORT YOUR FINDINGS TO THE OTHER LORDS.\nTHEN THEY WILL UNDERSTAND!"" ACCEPT(Y/N)?"
backpacks_full: "*** BACKPACKS FULL!"
diff --git a/engines/mm/mm1/maps/map38.cpp b/engines/mm/mm1/maps/map38.cpp
index a4fd59f2cab..12a64ba34da 100644
--- a/engines/mm/mm1/maps/map38.cpp
+++ b/engines/mm/mm1/maps/map38.cpp
@@ -55,57 +55,94 @@ void Map38::special00() {
}
void Map38::special01() {
+ send(SoundMessage(STRING["maps.map38.wall"]));
}
void Map38::special02() {
+ special03();
}
void Map38::special03() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->_mapPos.x = 0;
+ g_maps->changeMap(0xf03, 3);
+ }
+ ));
}
void Map38::special04() {
+ send(SoundMessage(STRING["maps.map38.banner"]));
}
void Map38::special05() {
+ encounter(&_data[669], &_data[682]);
}
void Map38::special06() {
+ encounter(&_data[690], &_data[705]);
}
void Map38::special07() {
+ encounter(&_data[715], &_data[724]);
}
void Map38::special08() {
+ encounter(&_data[733], &_data[743]);
}
void Map38::special09() {
+ encounter(&_data[753], &_data[764]);
}
void Map38::special10() {
+ encounter(&_data[775], &_data[788]);
}
void Map38::special11() {
+ encounter(&_data[801], &_data[816]);
}
void Map38::special12() {
+ encounter(&_data[831], &_data[840]);
}
void Map38::special13() {
+ encounter(&_data[849], &_data[862]);
}
void Map38::special14() {
+ encounter(&_data[875], &_data[890]);
}
void Map38::special15() {
+ send(SoundMessage(STRING["maps.map38.face1"]));
}
void Map38::special16() {
+ send(SoundMessage(STRING["maps.map38.face2"]));
}
void Map38::special17() {
+ send(SoundMessage(STRING["maps.map38.face3"]));
}
void Map38::special18() {
+ send(SoundMessage(STRING["maps.map38.face4"]));
+}
+
+void Map38::encounter(const byte *id1, const byte *id2) {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+
+ enc.clearMonsters();
+ for (int i = 0; i < 14 && *id1; ++i, ++id1, ++id2)
+ enc.addMonster(*id1, *id2);
+
+ enc._flag = true;
+ enc._levelIndex = 64;
+ enc.execute();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map38.h b/engines/mm/mm1/maps/map38.h
index eaa0c851699..c41649148e4 100644
--- a/engines/mm/mm1/maps/map38.h
+++ b/engines/mm/mm1/maps/map38.h
@@ -50,6 +50,7 @@ private:
void special16();
void special17();
void special18();
+ void encounter(const byte *id1, const byte *id2);
const SpecialFn SPECIAL_FN[19] = {
&Map38::special00,
Commit: fa504a9d1f97382842c71d2e029652739b57f273
https://github.com/scummvm/scummvm/commit/fa504a9d1f97382842c71d2e029652739b57f273
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: Added map 39
Changed paths:
A engines/mm/mm1/views/maps/ruby.cpp
A engines/mm/mm1/views/maps/ruby.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map37.h
engines/mm/mm1/maps/map38.cpp
engines/mm/mm1/maps/map38.h
engines/mm/mm1/maps/map39.cpp
engines/mm/mm1/maps/map39.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/ice_princess.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 85e761ed920..3f57d93ad95 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1363,3 +1363,12 @@ maps:
face4: "INSET IN THE WALL, A STONE FACE\nPROCLAIMS: ""OKRIM IS WATCHING.\nHE STUDIES YOUR WEAKNESSES!"""
wall: THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
ringing: "A STRANGE RINGING SOUND STARTLES\nTHE PARTY. YOU ARE TELEPORTED!"
+
+ map39:
+ message6: "ETCHED IN GOLD, MESSAGE 6 READS:\nBOOK-DONE.-A-SELF-THAT-FROM-KEY-YOU-\nBE-TO-SEEMS"
+ ruby1: "IN THE CENTER OF THE ROOM, A HUGE RUBY\nSTANDS ATOP A PEDESTAL. HEXAGONALLY\nSHAPED, IT GLOWS RHYTHMICALLY!\nMESMERIZED BY ITS LIGHT, YOU HEAR:\nGLASS THAT GLITTERS, RUBIES THAT GLOW\nWHEN I TWINKLE, I CAST A RAINBOW\nWHAT AM I? :\n> ..............."
+ ruby2: "WRONG! A BRIGHT FLASH..."
+ door_repels: "A SILVER DOOR REPELS YOU!"
+ door_glows: "A SILVER DOOR, YOUR SILVER KEY GLOWS!"
+ stairs_up: "STAIRS TO SURFACE, TAKE THEM (Y/N)?"
+ room: "THE ROOM IS PAINTED IN A BLACK AND\nWHITE CHECKERED PATTERN!"
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index b7404b70f9b..e40254185e4 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -112,6 +112,19 @@ void Map::redrawGame() {
g_events->findView("Game")->redraw();
}
+void Map::encounter(const byte *id1, const byte *id2) {
+ Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
+
+ enc.clearMonsters();
+ for (int i = 0; i < 14 && *id1; ++i, ++id1, ++id2)
+ enc.addMonster(*id1, *id2);
+
+ enc._flag = true;
+ enc._levelIndex = 64;
+ enc.execute();
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 725f9af4f1b..e5001fcffe6 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -122,6 +122,11 @@ protected:
*/
static void none160() {}
+ /**
+ * Generates an encounter based on the passed id arrays
+ */
+ void encounter(const byte *id1, const byte *id2);
+
public:
byte _walls[MAP_SIZE];
byte _states[MAP_SIZE];
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index e6082abecad..a4875501e3d 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -170,19 +170,6 @@ void Map37::special19() {
send(SoundMessage(STRING["maps.map37.archway"]));
}
-void Map37::encounter(const byte *id1, const byte *id2) {
- Game::Encounter &enc = g_globals->_encounters;
- g_maps->clearSpecial();
-
- enc.clearMonsters();
- for (int i = 0; i < 14 && *id1; ++i, ++id1, ++id2)
- enc.addMonster(*id1, *id2);
-
- enc._flag = true;
- enc._levelIndex = 64;
- enc.execute();
-}
-
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map37.h b/engines/mm/mm1/maps/map37.h
index bd8df14fba3..ab8ef7681e6 100644
--- a/engines/mm/mm1/maps/map37.h
+++ b/engines/mm/mm1/maps/map37.h
@@ -49,7 +49,6 @@ private:
void special15();
void special16();
void special19();
- void encounter(const byte *id1, const byte *id2);
const SpecialFn SPECIAL_FN[20] = {
&Map37::special00,
diff --git a/engines/mm/mm1/maps/map38.cpp b/engines/mm/mm1/maps/map38.cpp
index 12a64ba34da..572b30cb1c5 100644
--- a/engines/mm/mm1/maps/map38.cpp
+++ b/engines/mm/mm1/maps/map38.cpp
@@ -132,19 +132,6 @@ void Map38::special18() {
send(SoundMessage(STRING["maps.map38.face4"]));
}
-void Map38::encounter(const byte *id1, const byte *id2) {
- Game::Encounter &enc = g_globals->_encounters;
- g_maps->clearSpecial();
-
- enc.clearMonsters();
- for (int i = 0; i < 14 && *id1; ++i, ++id1, ++id2)
- enc.addMonster(*id1, *id2);
-
- enc._flag = true;
- enc._levelIndex = 64;
- enc.execute();
-}
-
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map38.h b/engines/mm/mm1/maps/map38.h
index c41649148e4..eaa0c851699 100644
--- a/engines/mm/mm1/maps/map38.h
+++ b/engines/mm/mm1/maps/map38.h
@@ -50,7 +50,6 @@ private:
void special16();
void special17();
void special18();
- void encounter(const byte *id1, const byte *id2);
const SpecialFn SPECIAL_FN[19] = {
&Map38::special00,
diff --git a/engines/mm/mm1/maps/map39.cpp b/engines/mm/mm1/maps/map39.cpp
index e72f23631d0..809380c2cb7 100644
--- a/engines/mm/mm1/maps/map39.cpp
+++ b/engines/mm/mm1/maps/map39.cpp
@@ -31,11 +31,11 @@ namespace Maps {
void Map39::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 19; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[70 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +44,95 @@ void Map39::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map39::special00() {
+ send(SoundMessage(STRING["maps.map39.message6"]));
+}
+
+void Map39::special01() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._flags[7] |= CHARFLAG7_1;
+ }
+
+ send(SoundMessage(
+ STRING["maps.map39.stairs_up"],
+ []() {
+ g_maps->_mapPos = Common::Point(9, 9);
+ g_maps->changeMap(0x703, 2);
+ }
+ ));
+}
+
+void Map39::special02() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0x702, 3);
+ }
+ ));
+}
+
+void Map39::special03() {
+ g_events->addView("Ruby");
+}
+
+void Map39::special04() {
+ if (g_globals->_party.hasItem(SILVER_KEY_ID)) {
+ send(SoundMessage(STRING["maps.map39.door_glows"]));
+ } else {
+ g_maps->_mapPos.y++;
+ updateGame();
+ send(SoundMessage(STRING["maps.map39.door_repels"]));
+ }
+}
+
+void Map39::special05() {
+ encounter(&_data[615], &_data[622]);
+}
+
+void Map39::special06() {
+ encounter(&_data[629], &_data[637]);
+}
+
+void Map39::special07() {
+ encounter(&_data[645], &_data[656]);
+}
+
+void Map39::special08() {
+ encounter(&_data[667], &_data[676]);
+}
+
+void Map39::special09() {
+ encounter(&_data[685], &_data[696]);
+}
+
+void Map39::special10() {
+ encounter(&_data[707], &_data[718]);
+}
+
+void Map39::special11() {
+ encounter(&_data[729], &_data[742]);
+}
+
+void Map39::special12() {
+ encounter(&_data[755], &_data[762]);
+}
+
+void Map39::special13() {
+ encounter(&_data[769], &_data[782]);
+}
+
+void Map39::special14() {
+ encounter(&_data[795], &_data[807]);
+}
+
+void Map39::special18() {
+ send(SoundMessage(STRING["maps.map39.room"]));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map39.h b/engines/mm/mm1/maps/map39.h
index e42a8a4047a..cee44c8a720 100644
--- a/engines/mm/mm1/maps/map39.h
+++ b/engines/mm/mm1/maps/map39.h
@@ -32,9 +32,42 @@ class Map39 : public Map {
typedef void (Map39:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special18();
- const SpecialFn SPECIAL_FN[1] = {
- &Map39::special00
+ const SpecialFn SPECIAL_FN[19] = {
+ &Map39::special00,
+ &Map39::special01,
+ &Map39::special02,
+ &Map39::special03,
+ &Map39::special04,
+ &Map39::special05,
+ &Map39::special06,
+ &Map39::special07,
+ &Map39::special08,
+ &Map39::special09,
+ &Map39::special10,
+ &Map39::special11,
+ &Map39::special12,
+ &Map39::special13,
+ &Map39::special14,
+ &Map39::special05,
+ &Map39::special05,
+ &Map39::special05,
+ &Map39::special18
};
public:
Map39() : Map(39, "rwl1", 0xF02) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 1b2504a48ed..afa16f9cc3e 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -53,6 +53,7 @@
#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/views/maps/resistances.h"
+#include "mm/mm1/views/maps/ruby.h"
#include "mm/mm1/views/maps/trivia.h"
#include "mm/mm1/views/maps/volcano_god.h"
#include "mm/mm1/views/maps/won_game.h"
@@ -104,6 +105,7 @@ private:
Views::Maps::Inspectron _inspectron;
Views::Maps::Lion _lion;
Views::Maps::Resistances _resistances;
+ Views::Maps::Ruby _ruby;
Views::Maps::Trivia _trivia;
Views::Maps::VolcanoGod _volcanoGod;
Views::Maps::WonGame _wonGame;
diff --git a/engines/mm/mm1/views/maps/ice_princess.cpp b/engines/mm/mm1/views/maps/ice_princess.cpp
index 51d540d8908..8dc46cc4496 100644
--- a/engines/mm/mm1/views/maps/ice_princess.cpp
+++ b/engines/mm/mm1/views/maps/ice_princess.cpp
@@ -49,7 +49,7 @@ void IcePrincess::answerEntered() {
close();
for (int i = 0; i < 4; ++i)
- properAnswer += map[ANSWER_OFFSET + i] & 0x7f + 64;
+ properAnswer += map[ANSWER_OFFSET + i] & 0x7f - 64;
if (_answer == properAnswer) {
InfoMessage msg(
diff --git a/engines/mm/mm1/views/maps/ruby.cpp b/engines/mm/mm1/views/maps/ruby.cpp
new file mode 100644
index 00000000000..d0619f9f879
--- /dev/null
+++ b/engines/mm/mm1/views/maps/ruby.cpp
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/ruby.h"
+#include "mm/mm1/maps/map39.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define ANSWER_OFFSET 477
+
+Ruby::Ruby() : AnswerEntry("Ruby", Common::Point(2, 9), 12) {
+ _bounds = getLineBounds(17, 24);
+}
+
+void Ruby::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map39.ruby1"]);
+}
+
+void Ruby::answerEntered() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Common::String properAnswer;
+ close();
+
+ for (int i = 0; i < 12 && map[ANSWER_OFFSET + i]; ++i)
+ properAnswer += map[ANSWER_OFFSET + i] - 64;
+
+ if (_answer == properAnswer) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._flags[5] |= CHARFLAG5_20;
+ }
+
+ g_events->addAction(KEYBIND_SEARCH);
+
+ } else {
+ g_maps->_mapPos.x = 9;
+ map.updateGame();
+
+ clearSurface();
+ writeString(0, 1, STRING["maps.map39.ruby2"]);
+ close();
+ }
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/ruby.h b/engines/mm/mm1/views/maps/ruby.h
new file mode 100644
index 00000000000..dbf3d0acfdc
--- /dev/null
+++ b/engines/mm/mm1/views/maps/ruby.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_RUBY_H
+#define MM1_VIEWS_MAPS_RUBY_H
+
+#include "mm/mm1/views/maps/answer_entry.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Ruby : public AnswerEntry {
+protected:
+ void answerEntered() override;
+
+public:
+ Ruby();
+ virtual ~Ruby() {}
+
+ void draw() override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index f30a4acdf83..dd4d056c25d 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -64,6 +64,7 @@ MODULE_OBJS := \
mm1/views/maps/lion.o \
mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \
+ mm1/views/map/ruby.o \
mm1/views/maps/trivia.o \
mm1/views/maps/volcano_god.o \
mm1/views/maps/won_game.o \
Commit: 58c98d2d4b4971fb3f3965546352060a8ae9e5a5
https://github.com/scummvm/scummvm/commit/58c98d2d4b4971fb3f3965546352060a8ae9e5a5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: Added map 40
Changed paths:
A engines/mm/mm1/views/maps/lord_archer.cpp
A engines/mm/mm1/views/maps/lord_archer.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map40.cpp
engines/mm/mm1/maps/map40.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3f57d93ad95..50e001bdc12 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1372,3 +1372,16 @@ maps:
door_glows: "A SILVER DOOR, YOUR SILVER KEY GLOWS!"
stairs_up: "STAIRS TO SURFACE, TAKE THEM (Y/N)?"
room: "THE ROOM IS PAINTED IN A BLACK AND\nWHITE CHECKERED PATTERN!"
+
+ map40:
+ message2: "ETCHED IN GOLD, MESSAGE 2 READS:\nONE,-RIDDLES-VALUE-YOU-YOU-5-CARD-MUST-\nCLAIMED.-DREAMS,-..."
+ archer: """I AM LORD ARCHER, THE RAVEN,\nI TAKE FROM THOSE WHO HAVE AND GIVE TO\nTHOSE WHO HAVE NOT! SUBMIT (Y/N)?"""
+ giants: "GIANTS HURL BOULDERS!"
+ button: "A BUTTON ON THE WALL, PUSH IT (Y/N)?"
+ squish: "SQUISH! THE PARTY IS IMPALED ON A WALL\nOF SPEARS!"
+ boulder: "A BOULDER SAYS:""THERE SHOULD BE 5 TESTS"""
+ test1: "THE FIRST TEST"
+ test2: "THE SECOND TEST"
+ test3: "THE THIRD TEST"
+ test4: "THE FOURTH TEST"
+ conveyor_belt: "CONVEYOR BELT..."
diff --git a/engines/mm/mm1/maps/map40.cpp b/engines/mm/mm1/maps/map40.cpp
index 61bd81390aa..55a1ae795e7 100644
--- a/engines/mm/mm1/maps/map40.cpp
+++ b/engines/mm/mm1/maps/map40.cpp
@@ -29,13 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 363
+#define VAL2 831
+#define GOLD 832
+
void Map40::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[74 + i]) {
(this->*SPECIAL_FN[i])();
} else {
@@ -44,14 +48,156 @@ void Map40::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (_data[VAL1]) {
+ checkPartyDead();
+ } else {
+ _data[VAL2]++;
+ g_maps->_mapPos.y++;
+ updateGame();
+ send(SoundMessage(STRING["maps.map40.conveyor_belt"]));
+ }
}
void Map40::special00() {
+ send(SoundMessage(STRING["maps.map40.message2"]));
+}
+
+void Map40::special01() {
+ g_maps->clearSpecial();
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._flags[7] |= CHARFLAG7_40;
+ }
+
+ g_events->addView("LordArcher");
+}
+
+void Map40::special02() {
+ reduceHP();
+ send(SoundMessage(STRING["maps.map40.giants"]));
+}
+
+void Map40::special03() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0xf02, 3);
+ }
+ ));
+}
+
+void Map40::special04() {
+ send(SoundMessage(
+ STRING["maps.map40.button"],
+ []() {
+ Map40 &map = *static_cast<Map40 *>(g_maps->_currentMap);
+ map[VAL1]++;
+ }
+ ));
+}
+
+void Map40::special05() {
+ encounter(&_data[588], &_data[601]);
+}
+
+void Map40::special06() {
+ encounter(&_data[614], &_data[621]);
+}
+
+void Map40::special07() {
+ encounter(&_data[628], &_data[640]);
+}
+
+void Map40::special08() {
+ encounter(&_data[652], &_data[658]);
+}
+
+void Map40::special09() {
+ encounter(&_data[664], &_data[675]);
+}
+
+void Map40::special10() {
+ encounter(&_data[686], &_data[700]);
+}
+
+void Map40::special11() {
+ encounter(&_data[714], &_data[726]);
+}
+
+void Map40::special12() {
+ encounter(&_data[738], &_data[750]);
+}
+
+void Map40::special13() {
+ encounter(&_data[762], &_data[776]);
+}
+
+void Map40::special14() {
+ encounter(&_data[790], &_data[802]);
+}
+
+void Map40::special15() {
+ if (_data[VAL2]) {
+ _data[VAL2] = 0;
+ reduceHP();
+ reduceHP();
+ send(SoundMessage(STRING["maps.map40.squish"]));
+
+ } else {
+ none160();
+ }
+}
+
+void Map40::special16() {
+ send(SoundMessage(STRING["maps.map40.boulder"]));
+}
+
+void Map40::special17() {
+ send(SoundMessage(STRING["maps.map40.test1"]));
+}
+
+void Map40::special18() {
+ send(SoundMessage(STRING["maps.map40.test2"]));
+}
+
+void Map40::special19() {
+ send(SoundMessage(STRING["maps.map40.test3"]));
+}
+
+void Map40::special20() {
+ send(SoundMessage(STRING["maps.map40.test4"]));
+}
+
+void Map40::archerResist() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ enc.clearMonsters();
+ for (int i = 0; i < 6; ++i)
+ enc.addMonster(12, 10);
+ enc.addMonster(15, 12);
+
+ enc._flag = true;
+ enc._levelIndex = 112;
+ enc.execute();
+}
+
+void Map40::archerSubmit() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if (g_globals->_party[i]._gold) {
+ // As long as even one character has gold, Archer
+ // will take all of the party's gold
+ WRITE_LE_UINT16(&_data[GOLD], 0);
+ break;
+ }
+ }
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._gold = READ_LE_UINT16(&_data[GOLD]);
+ }
+
+ g_maps->_mapPos = Common::Point(8, 5);
+ g_maps->changeMap(0x604, 1);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map40.h b/engines/mm/mm1/maps/map40.h
index 78d383375a5..d24deba9f13 100644
--- a/engines/mm/mm1/maps/map40.h
+++ b/engines/mm/mm1/maps/map40.h
@@ -32,9 +32,51 @@ class Map40 : public Map {
typedef void (Map40:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special17();
+ void special18();
+ void special19();
+ void special20();
- const SpecialFn SPECIAL_FN[1] = {
- &Map40::special00
+ const SpecialFn SPECIAL_FN[23] = {
+ &Map40::special00,
+ &Map40::special01,
+ &Map40::special02,
+ &Map40::special03,
+ &Map40::special04,
+ &Map40::special05,
+ &Map40::special06,
+ &Map40::special07,
+ &Map40::special08,
+ &Map40::special09,
+ &Map40::special10,
+ &Map40::special11,
+ &Map40::special12,
+ &Map40::special13,
+ &Map40::special14,
+ &Map40::special15,
+ &Map40::special16,
+ &Map40::special17,
+ &Map40::special18,
+ &Map40::special19,
+ &Map40::special20,
+ &Map40::special02,
+ &Map40::special02
};
public:
Map40() : Map(40, "rwl2", 0x702) {}
@@ -43,6 +85,16 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Called when party chooses to resist Lord Archer
+ */
+ void archerResist();
+
+ /**
+ * Called when party chooses to submit to Lord Archer
+ */
+ void archerSubmit();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index afa16f9cc3e..46e840d5d32 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -51,6 +51,7 @@
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/views/maps/lion.h"
+#include "mm/mm1/views/maps/lord_archer.h"
#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/ruby.h"
@@ -104,6 +105,7 @@ private:
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Inspectron _inspectron;
Views::Maps::Lion _lion;
+ Views::Maps::LordArcher _lordArcher;
Views::Maps::Resistances _resistances;
Views::Maps::Ruby _ruby;
Views::Maps::Trivia _trivia;
diff --git a/engines/mm/mm1/views/maps/lord_archer.cpp b/engines/mm/mm1/views/maps/lord_archer.cpp
new file mode 100644
index 00000000000..6cbe886b10e
--- /dev/null
+++ b/engines/mm/mm1/views/maps/lord_archer.cpp
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/lord_archer.h"
+#include "mm/mm1/maps/map40.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+LordArcher::LordArcher() : TextView("LordArcher") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool LordArcher::msgFocus(const FocusMessage &msg) {
+ Sound::sound(SOUND_3);
+ return TextView::msgFocus(msg);
+}
+
+void LordArcher::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map40.archer"]);
+}
+
+bool LordArcher::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_y || msg.keycode == Common::KEYCODE_n) {
+ MM1::Maps::Map40 &map = *static_cast<MM1::Maps::Map40 *>(g_maps->_currentMap);
+ close();
+
+ if (msg.keycode == Common::KEYCODE_y) {
+ map.archerSubmit();
+ } else {
+ map.archerResist();
+ }
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/lord_archer.h b/engines/mm/mm1/views/maps/lord_archer.h
new file mode 100644
index 00000000000..7d8bbc5d2e0
--- /dev/null
+++ b/engines/mm/mm1/views/maps/lord_archer.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_LORD_ARCHER_H
+#define MM1_VIEWS_MAPS_LORD_ARCHER_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class LordArcher : public TextView {
+public:
+ LordArcher();
+ virtual ~LordArcher() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index dd4d056c25d..3a74b395027 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -62,6 +62,7 @@ MODULE_OBJS := \
mm1/views/maps/ice_princess.o \
mm1/views/maps/inspectron.o \
mm1/views/maps/lion.o \
+ mm1/views/maps/lord_archer.o \
mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \
mm1/views/map/ruby.o \
Commit: 2242171342425e0b45b3cb88d0c58252ab3add72
https://github.com/scummvm/scummvm/commit/2242171342425e0b45b3cb88d0c58252ab3add72
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:27+01:00
Commit Message:
MM: MM1: Added map 41
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map41.cpp
engines/mm/mm1/maps/map41.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 50e001bdc12..3af04a0c6d0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1385,3 +1385,16 @@ maps:
test3: "THE THIRD TEST"
test4: "THE FOURTH TEST"
conveyor_belt: "CONVEYOR BELT..."
+
+ map41:
+ message3: "ETCHED IN GOLD, MESSAGE 3 READS:\nFOR-TASKS-AND-RATING.-BE-FROM-6TH-\nFRUSTRATIONS!-THE-TO-IN"
+ dung: "MINOTAUR DUNG SLUSHES BENEATH YOU!"
+ sign1: "THE ENCHANTED CHAMBER"
+ sign2: "CLEPTOMIAN GUILD, DO NOT DISTURB!"
+ sign3: "THE COUNCIL OF STRENGTH IS IN SESSION"
+ sign4: "THE UGLIES CLUB - MEMBERS ONLY!"
+ sign5: "SPECIMEN TANK - KEEP CLOSED"
+ stairs_up: "SPIRALLING STAIRS GO UP,TAKE THEM (Y/N)?"
+ room: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+ tapestry1: "A TAPESTRY ON THE WALL DEPICTS A GRAY\nMINOTAUR STOMPING ON A GROUP OF KNIGHTS."
+ tapestry2: "A TAPESTRY ON THE WALL DEPICTS\nA KINGDOM RULED BY MINOTAURS"
diff --git a/engines/mm/mm1/maps/map41.cpp b/engines/mm/mm1/maps/map41.cpp
index d8e69c3ba52..6a17dfae587 100644
--- a/engines/mm/mm1/maps/map41.cpp
+++ b/engines/mm/mm1/maps/map41.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map41::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 25; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[76 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,118 @@ void Map41::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ checkPartyDead();
}
void Map41::special00() {
+ send(SoundMessage(STRING["maps.map40.message3"]));
+}
+
+void Map41::special01() {
+ send(SoundMessage(
+ STRING["maps.maps40.stairs_up"],
+ []() {
+ g_maps->_mapPos = Common::Point(14, 2);
+ g_maps->changeMap(0x101, 2);
+ }
+ ));
+}
+
+void Map41::special02() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0x704, 3);
+ }
+ ));
+}
+
+void Map41::special03() {
+ special02();
+}
+
+void Map41::special04() {
+ send(SoundMessage(STRING["maps.map40.dung"]));
+}
+
+void Map41::special05() {
+ encounter(&_data[509], &_data[519]);
+}
+
+void Map41::special06() {
+ encounter(&_data[529], &_data[542]);
+}
+
+void Map41::special07() {
+ encounter(&_data[555], &_data[563]);
+}
+
+void Map41::special08() {
+ encounter(&_data[571], &_data[586]);
+}
+
+void Map41::special09() {
+ encounter(&_data[601], &_data[613]);
+}
+
+void Map41::special10() {
+ encounter(&_data[625], &_data[633]);
+}
+
+void Map41::special11() {
+ encounter(&_data[641], &_data[650]);
+}
+
+void Map41::special12() {
+ encounter(&_data[659], &_data[670]);
+}
+
+void Map41::special13() {
+ encounter(&_data[683], &_data[691]);
+}
+
+void Map41::special14() {
+ encounter(&_data[699], &_data[710]);
+}
+
+void Map41::special16() {
+ showSign(STRING["maps.map41.sign1"]);
+}
+
+void Map41::special17() {
+ showSign(STRING["maps.map41.sign2"]);
+}
+
+void Map41::special18() {
+ showSign(STRING["maps.map41.sign3"]);
+}
+
+void Map41::special19() {
+ showSign(STRING["maps.map41.sign4"]);
+}
+
+void Map41::special20() {
+ showSign(STRING["maps.map41.sign5"]);
+}
+
+void Map41::special21() {
+ send(SoundMessage(STRING["maps.map41.room"]));
+}
+
+void Map41::special22() {
+ send(SoundMessage(STRING["maps.map41.tapestry1"]));
+}
+
+void Map41::special23() {
+ send(SoundMessage(STRING["maps.map41.tapestry2"]));
+}
+
+void Map41::showSign(const Common::String &line) {
+ send(SoundMessage(
+ 0, 1, STRING["maps.sign"],
+ 0, 2, line
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map41.h b/engines/mm/mm1/maps/map41.h
index 2feeb4c47f2..10011a9fe67 100644
--- a/engines/mm/mm1/maps/map41.h
+++ b/engines/mm/mm1/maps/map41.h
@@ -32,9 +32,56 @@ class Map41 : public Map {
typedef void (Map41:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special16();
+ void special17();
+ void special18();
+ void special19();
+ void special20();
+ void special21();
+ void special22();
+ void special23();
+ void showSign(const Common::String &line);
- const SpecialFn SPECIAL_FN[1] = {
- &Map41::special00
+ const SpecialFn SPECIAL_FN[25] = {
+ &Map41::special00,
+ &Map41::special01,
+ &Map41::special02,
+ &Map41::special03,
+ &Map41::special04,
+ &Map41::special05,
+ &Map41::special06,
+ &Map41::special07,
+ &Map41::special08,
+ &Map41::special09,
+ &Map41::special10,
+ &Map41::special11,
+ &Map41::special12,
+ &Map41::special13,
+ &Map41::special14,
+ &Map41::special14,
+ &Map41::special16,
+ &Map41::special17,
+ &Map41::special18,
+ &Map41::special19,
+ &Map41::special20,
+ &Map41::special21,
+ &Map41::special22,
+ &Map41::special23,
+ &Map41::special04
};
public:
Map41() : Map(41, "enf1", 0xF04) {}
Commit: 3458be7e4934b914bd3b54340e063f42cee5e22a
https://github.com/scummvm/scummvm/commit/3458be7e4934b914bd3b54340e063f42cee5e22a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:28+01:00
Commit Message:
MM: MM1: Added map 42
Changed paths:
A engines/mm/mm1/views/maps/dog_statue.cpp
A engines/mm/mm1/views/maps/dog_statue.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map42.cpp
engines/mm/mm1/maps/map42.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3af04a0c6d0..1d45d70d10f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1398,3 +1398,11 @@ maps:
room: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
tapestry1: "A TAPESTRY ON THE WALL DEPICTS A GRAY\nMINOTAUR STOMPING ON A GROUP OF KNIGHTS."
tapestry2: "A TAPESTRY ON THE WALL DEPICTS\nA KINGDOM RULED BY MINOTAURS"
+
+ map42:
+ message9: "ETCHED IN GOLD, MESSAGE 9 READS:\nSUCCESSFUL-THAT-TRAINING,-THE-WORTHY-\nTHE-VISIT-YET-INNER-REALITY,-ORDER,"
+ defeated: "THE MASTER OF THIS STRONGHOLD\nHAS BEEN DEFEATED!"
+ sign1: "ENTER THE MAZE OF THE MINOTAUR...\nIF YOU DARE!"
+ statue1: "STANDING ATOP A PEDESTAL IN THE CENTER\nOF THE ROOM IS A STATUE OF A SMALL SABLEAND WHITE DOG. "
+ statue2: "IT COMES TO LIFE AND\nSPEAKS,""CONGRATULATIONS, YOU'VE\nCOMPLETED A MAJOR QUEST (+10000 EXP)\nREMEMBER B.J.!"""
+ statue3: "DESECRATE IT (Y/N)?"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index a10676de666..e81731aad10 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -71,7 +71,7 @@ enum CharFlags0 {
CHARFLAG0_ZAM_CLUE = 0x10,
CHARFLAG0_FOUND_CHEST = 0x20,
CHARFLAG0_40 = 0x40,
- CHARFLAG0_80 = 0x80
+ CHARFLAG0_DOG_STATUE = 0x80
};
enum CharFlags1 {
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
index 3299ae75878..9d7cc3ccb59 100644
--- a/engines/mm/mm1/maps/map42.cpp
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -29,14 +29,16 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define MONSTER_COUNT 151
+#define VAL1 259
+
void Map42::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 25; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[76 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +46,139 @@ void Map42::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ g_maps->_mapPos.y = 4;
+ updateGame();
}
void Map42::special00() {
+ g_events->addView("WhiteDog");
+}
+
+void Map42::special01() {
+ send(SoundMessage(STRING["maps.map42.message4"]));
+}
+
+void Map42::special02() {
+ Game::Encounter &enc = g_globals->_encounters;
+
+ if (_data[VAL1]) {
+ send(SoundMessage(STRING["maps.map42.defeated"]));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._flags[5] |= CHARFLAG5_40;
+ }
+ } else {
+ _data[VAL1]++;
+
+ enc.clearMonsters();
+ enc.addMonster(14, 12);
+ for (int i = 1; i < 13; ++i)
+ enc.addMonster(8, 5);
+
+ enc._flag = true;
+ enc._levelIndex = 64;
+ enc.execute();
+ }
+}
+
+void Map42::special03() {
+ send(SoundMessage(STRING["maps.map42.sign1"]));
+}
+
+void Map42::special04() {
+ Sound::sound(SOUND_2);
+ g_maps->_mapPos.x++;
+ if (g_maps->_mapPos.x >= 10)
+ g_maps->_mapPos.x = 6;
+
+ updateGame();
+}
+
+void Map42::special05() {
+ encounter(&_data[611], &_data[624]);
+}
+
+void Map42::special06() {
+ encounter(&_data[637], &_data[648]);
+}
+
+void Map42::special07() {
+ encounter(&_data[659], &_data[668]);
+}
+
+void Map42::special08() {
+ encounter(&_data[677], &_data[686]);
+}
+
+void Map42::special09() {
+ encounter(&_data[695], &_data[704]);
+}
+
+void Map42::special10() {
+ encounter(&_data[713], &_data[724]);
+}
+
+void Map42::special11() {
+ encounter(&_data[735], &_data[743]);
+}
+
+void Map42::special12() {
+ encounter(&_data[751], &_data[759]);
+}
+
+void Map42::special13() {
+ encounter(&_data[767], &_data[777]);
+}
+
+void Map42::special14() {
+ encounter(&_data[787], &_data[796]);
+}
+
+void Map42::special15() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0xf04, 3);
+ }
+ ));
+}
+
+void Map42::special17() {
+ g_globals->_treasure[6] = 76;
+ g_globals->_treasure[7] = 29;
+ g_globals->_treasure[2] = 8;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map42::dogSuccess() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[0] = CHARFLAG0_DOG_STATUE;
+ c._exp += 10000;
+ }
+
+ g_globals->_treasure[5] = GOLD_KEY_ID;
+ g_globals->_treasure[1] = 2;
+ none160();
+}
+
+void Map42::dogDesecrate() {
+ Game::Encounter &enc = g_globals->_encounters;
+ redrawGame();
+
+ byte &count = _data[MONSTER_COUNT];
+ count *= 2;
+ if (count >= 16)
+ count = 13;
+
+ enc.clearMonsters();
+ for (int i = 0; i < (int)count; ++i)
+ enc.addMonster(4, 10);
+
+ enc._flag = true;
+ enc._levelIndex = 20;
+ enc.execute();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map42.h b/engines/mm/mm1/maps/map42.h
index e0d0ae68954..3f544cffe98 100644
--- a/engines/mm/mm1/maps/map42.h
+++ b/engines/mm/mm1/maps/map42.h
@@ -32,9 +32,49 @@ class Map42 : public Map {
typedef void (Map42:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special17();
- const SpecialFn SPECIAL_FN[1] = {
- &Map42::special00
+ const SpecialFn SPECIAL_FN[25] = {
+ &Map42::special00,
+ &Map42::special01,
+ &Map42::special02,
+ &Map42::special03,
+ &Map42::special04,
+ &Map42::special05,
+ &Map42::special06,
+ &Map42::special07,
+ &Map42::special08,
+ &Map42::special09,
+ &Map42::special10,
+ &Map42::special11,
+ &Map42::special12,
+ &Map42::special13,
+ &Map42::special14,
+ &Map42::special15,
+ &Map42::special15,
+ &Map42::special17,
+ &Map42::special17,
+ &Map42::special03,
+ &Map42::special03,
+ &Map42::special03,
+ &Map42::special04,
+ &Map42::special04,
+ &Map42::special04
};
public:
Map42() : Map(42, "enf2", 0x704) {}
@@ -43,6 +83,16 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Succeeded in the necessary quests
+ */
+ void dogSuccess();
+
+ /**
+ * Desecrating the dog statue
+ */
+ void dogDesecrate();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 46e840d5d32..b6e2f698df5 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -46,6 +46,7 @@
#include "mm/mm1/views/maps/alien.h"
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
+#include "mm/mm1/views/maps/dog_statue.h"
#include "mm/mm1/views/maps/ghost.h"
#include "mm/mm1/views/maps/giant.h"
#include "mm/mm1/views/maps/ice_princess.h"
@@ -100,6 +101,7 @@ private:
Views::Maps::CloakedPrisoner _cloakedPrisoner;
Views::Maps::DemonPrisoner _demonPrisoner;
Views::Maps::ManPrisoner _manPrisoner;
+ Views::Maps::DogStatue _dogStatue;
Views::Maps::Ghost _ghost;
Views::Maps::Giant _giant;
Views::Maps::IcePrincess _icePrincess;
diff --git a/engines/mm/mm1/views/maps/dog_statue.cpp b/engines/mm/mm1/views/maps/dog_statue.cpp
new file mode 100644
index 00000000000..6ff6d7310e0
--- /dev/null
+++ b/engines/mm/mm1/views/maps/dog_statue.cpp
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/dog_statue.h"
+#include "mm/mm1/maps/map42.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+DogStatue::DogStatue() : TextView("DogStatue") {
+ _bounds = getLineBounds(17, 24);
+}
+
+bool DogStatue::msgFocus(const FocusMessage &msg) {
+ Sound::sound(SOUND_2);
+
+ _completedQuests = false;
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ if ((g_globals->_party[i]._flags[0] &
+ (CHARFLAG0_COURIER3 | CHARFLAG0_FOUND_CHEST | CHARFLAG0_40)) ==
+ (CHARFLAG0_COURIER3 | CHARFLAG0_FOUND_CHEST | CHARFLAG0_40)) {
+ _completedQuests = true;
+ break;
+ }
+ }
+
+ return TextView::msgFocus(msg);
+}
+
+void DogStatue::draw() {
+ MM1::Maps::Map42 &map = *static_cast<MM1::Maps::Map42 *>(g_maps->_currentMap);
+
+ clearSurface();
+ writeString(0, 0, STRING["maps.map42.statue1"]);
+
+ if (_completedQuests) {
+ writeString(0, 2, STRING["maps.map42.statue2"]);
+ map.dogSuccess();
+
+ } else {
+ writeString(0, 3, STRING["maps.map42.statue3"]);
+ }
+}
+
+bool DogStatue::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_y || msg.keycode == Common::KEYCODE_n) {
+ MM1::Maps::Map42 &map = *static_cast<MM1::Maps::Map42 *>(g_maps->_currentMap);
+ close();
+
+ if (msg.keycode == Common::KEYCODE_y) {
+ close();
+ map.dogDesecrate();
+ } else {
+ close();
+ }
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/dog_statue.h b/engines/mm/mm1/views/maps/dog_statue.h
new file mode 100644
index 00000000000..18076bcbc7d
--- /dev/null
+++ b/engines/mm/mm1/views/maps/dog_statue.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_DOG_STATUE_H
+#define MM1_VIEWS_MAPS_DOG_STATUE_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class DogStatue : public TextView {
+private:
+ bool _completedQuests = false;
+public:
+ DogStatue();
+ virtual ~DogStatue() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 3a74b395027..bdcda9857e5 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -55,6 +55,7 @@ MODULE_OBJS := \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
mm1/views/maps/chess.o \
+ mm1/views/maps/dog_statue.o \
mm1/views/maps/ghost.o \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
Commit: 6bcc5cd66af3896ae87ba8ae5d1289e9eaf83de5
https://github.com/scummvm/scummvm/commit/6bcc5cd66af3896ae87ba8ae5d1289e9eaf83de5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:28+01:00
Commit Message:
MM: MM1: Added map 43
Changed paths:
A engines/mm/mm1/views/maps/lord_ironfist.cpp
A engines/mm/mm1/views/maps/lord_ironfist.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map43.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 1d45d70d10f..ae732c82234 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1406,3 +1406,24 @@ maps:
statue1: "STANDING ATOP A PEDESTAL IN THE CENTER\nOF THE ROOM IS A STATUE OF A SMALL SABLEAND WHITE DOG. "
statue2: "IT COMES TO LIFE AND\nSPEAKS,""CONGRATULATIONS, YOU'VE\nCOMPLETED A MAJOR QUEST (+10000 EXP)\nREMEMBER B.J.!"""
statue3: "DESECRATE IT (Y/N)?"
+
+ map43:
+ exit: "EXIT CASTLE, (Y/N)?"
+ button: "BUTTON ON THE WALL, PUSH IT (Y/N)?"
+ tower: "THE TOWER"
+ throne_room: "THRONE ROOM"
+ ironfist1: "LORD IRONFIST SPEAKS:\n"
+ ironfist2: """YOUR SERVICES ARE NEEDED!"" ACCEPT(Y/N)?"
+ ironfist3: """RETURN NOT UNTIL THY QUEST IS COMPLETE"""
+ ironfist4: """SORRY, BUT SINCE YOU ARE CURRENTLY\nQUESTED, I CAN'T ENGAGE YOUR SERVICES."""
+ ironfist5: "WELL DONE, QUEST COMPLETE! +%u EXP"
+ message_b: "ETCHED IN SILVER, MESSAGE B READS:\nRSTIA-,E1,;/11RN;/M-"
+ guards: "CASTLE GUARDS EXCLAIM,\n""NO MERCHANTS PASS! BEGONE PEASANTS."""
+ quests:
+ 0: "FIND THE STRONGHOLD IN RAVENS WOOD"
+ 1: "FIND LORD KILBURN"
+ 2: "DISCOVER THE SECRET OF PORTSMITH"
+ 3: "FIND THE PIRATES SECRET COVE"
+ 4: "FIND THE SHIPWRECK OF THE JOLLY RAVEN"
+ 5: "DEFEAT THE PIRATE GHOST SHIP ANARCHIST"
+ 6: "DEFEAT THE STRONGHOLD IN RAVENS WOOD"
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 63bee303fdb..6cd88fb8259 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -29,14 +29,25 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 142
+
+static const byte MATCH_ITEMS[7] = {
+ 0, 0, MAP_OF_DESERT_ID, 0, 0, 0, 0
+};
+static const byte MATCH_FLAGS[8] = {
+ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80
+};
+static const uint16 QUEST_EXPERIENCE[7] = {
+ 1000, 2000, 3000, 4000, 6000, 8000, 10000
+};
+
void Map43::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < _data[50]; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[60 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +55,157 @@ void Map43::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map43::special00() {
+ g_events->addView("DemonPrisoner");
+}
+
+void Map43::special01() {
+ _data[VAL1] = 0;
+ if (g_maps->_forwardMask == DIRMASK_E) {
+ send(SoundMessage(
+ STRING["maps.map43.exit"],
+ []() {
+ g_maps->_mapPos = Common::Point(9, 13);
+ g_maps->changeMap(0x101, 2);
+ }
+ ));
+ } else {
+ none160();
+ }
+}
+
+void Map43::special02() {
+ send(SoundMessage(
+ STRING["maps.map43.button"],
+ []() {
+ Map43 &map = *static_cast<Map43 *>(g_maps->_currentMap);
+ map._walls[101] = 17;
+ map.none160();
+ }
+ ));
+}
+
+void Map43::special03() {
+ send(SoundMessage(STRING["maps.map43.message_b"]));
+}
+
+void Map43::special04() {
+ if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
+ g_maps->_mapPos = Common::Point(9, 13);
+ g_maps->changeMap(0x101, 2);
+ send(SoundMessage(STRING["maps.map43.guards"]));
+ }
+}
+
+void Map43::special05() {
+ updateFlags();
+ send("GameView", DrawMonsterMessage(7));
+ g_events->addView("LordIronfist");
+}
+
+void Map43::special06() {
+ if (_data[VAL1]) {
+ g_globals->_treasure[6] = 80;
+ g_globals->_treasure[7] = 70;
+ g_maps->clearSpecial();
+ g_events->addAction(KEYBIND_SEARCH);
+ } else {
+ Game::Encounter &enc = g_globals->_encounters;
+ _data[VAL1]++;
+
+ enc.clearMonsters();
+ for (int i = 0; i < 8; ++i)
+ enc.addMonster(13, 7);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+ enc.execute();
+ }
+}
+
+void Map43::special07() {
+ send(SoundMessage(STRING["maps.map43.tower"]));
+}
+
+void Map43::special08() {
+ send(SoundMessage(STRING["maps.map43.throne_room"]));
+}
+
+void Map43::updateFlags() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ int counte = c._equipped.size();
+ int count = counte + c._backpack.size();
+ for (int itemIdx = 0; itemIdx < count; ++itemIdx) {
+ byte itemId = (itemIdx < counte) ?
+ c._equipped[itemIdx]._id : c._backpack[itemIdx - counte]._id;
+
+ // Scan list of items to match against
+ for (int arrIdx = 0; arrIdx < 7; ++arrIdx) {
+ if (itemId == MATCH_ITEMS[arrIdx]) {
+ c._flags[7] |= MATCH_FLAGS[arrIdx];
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Map43::acceptQuest() {
+ Character &leader = g_globals->_party[0];
+ byte flags = leader._flags[10];
+
+ // Find quest that hasn't been done yet
+ int questNum;
+ for (questNum = 0; flags && questNum < 8; ++questNum, flags >>= 1) {
+ if (!(flags & 1))
+ break;
+ }
+ if (questNum == 8) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[10] = CHARFLAG8_80;
+ c._flags[7] = CHARFLAG5_80;
+ }
+ }
+
+ // Assign the quest to all party characters
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = questNum;
+ }
+
+ // Draw the scene
+ g_maps->_mapPos.x++;
+ redrawGame();
+}
+
+Common::String Map43::checkQuestComplete() {
+ Character &leader = g_globals->_party[0];
+ int qIndex = leader._quest - 7;
+
+ if (leader._flags[7] & MATCH_FLAGS[qIndex] & 0x7f) {
+ // The quest was complete
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = 0;
+ c._flags[10] |= MATCH_FLAGS[qIndex];
+ c._exp += QUEST_EXPERIENCE[qIndex];
+ }
+
+ return Common::String::format(
+ STRING["maps.map43.ironfist5"].c_str(),
+ QUEST_EXPERIENCE[qIndex]);
+ } else {
+ // The quest isn't yet complete
+ return STRING["maps.map43.ironfist3"];
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map43.h b/engines/mm/mm1/maps/map43.h
index 4297236b737..7d361fc7d76 100644
--- a/engines/mm/mm1/maps/map43.h
+++ b/engines/mm/mm1/maps/map43.h
@@ -32,9 +32,26 @@ class Map43 : public Map {
typedef void (Map43:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void updateFlags();
- const SpecialFn SPECIAL_FN[1] = {
- &Map43::special00
+ const SpecialFn SPECIAL_FN[9] = {
+ &Map43::special00,
+ &Map43::special01,
+ &Map43::special02,
+ &Map43::special03,
+ &Map43::special04,
+ &Map43::special05,
+ &Map43::special06,
+ &Map43::special07,
+ &Map43::special08
};
public:
Map43() : Map(43, "whitew", 0xA11) {}
@@ -43,6 +60,17 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Accepts a quest from Inspectron
+ */
+ void acceptQuest();
+
+ /**
+ * Does a check for whether Inspectron's current quest
+ * is complete or not
+ */
+ Common::String checkQuestComplete();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index b6e2f698df5..727e9f69855 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -53,6 +53,7 @@
#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/lord_archer.h"
+#include "mm/mm1/views/maps/lord_ironfist.h"
#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/ruby.h"
@@ -108,6 +109,7 @@ private:
Views::Maps::Inspectron _inspectron;
Views::Maps::Lion _lion;
Views::Maps::LordArcher _lordArcher;
+ Views::Maps::LordIronfist _lordIronfist;
Views::Maps::Resistances _resistances;
Views::Maps::Ruby _ruby;
Views::Maps::Trivia _trivia;
diff --git a/engines/mm/mm1/views/maps/lord_ironfist.cpp b/engines/mm/mm1/views/maps/lord_ironfist.cpp
new file mode 100644
index 00000000000..5981073dffd
--- /dev/null
+++ b/engines/mm/mm1/views/maps/lord_ironfist.cpp
@@ -0,0 +1,100 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/lord_ironfist.h"
+#include "mm/mm1/maps/map43.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+LordIronfist::LordIronfist() : TextView("LordIronfist") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool LordIronfist::msgFocus(const FocusMessage &msg) {
+ g_globals->_currCharacter = &g_globals->_party[0];
+ _canAccept = !g_globals->_currCharacter->_quest;
+ Sound::sound(SOUND_2);
+
+ return TextView::msgFocus(msg);
+}
+
+void LordIronfist::draw() {
+ MM1::Maps::Map43 &map = *static_cast<MM1::Maps::Map43 *>(g_maps->_currentMap);
+ clearSurface();
+
+ if (_canAccept) {
+ send(SoundMessage(
+ 0, 1, STRING["maps.map43.ironfist1"],
+ 0, 2, STRING["maps.map43.ironfist2"]
+ ));
+ } else {
+ int questNum = g_globals->_party[0]._quest;
+ Common::String line;
+
+ if (questNum < 8)
+ line = map.checkQuestComplete();
+ else
+ line = STRING["maps.map43.ironfist4"];
+
+ g_maps->_mapPos.x++;
+ map.redrawGame();
+
+ clearSurface();
+ send(SoundMessage(
+ 0, 1, STRING["maps.map43.ironfist1"],
+ 0, 2, line
+ ));
+ close();
+ }
+}
+
+bool LordIronfist::msgKeypress(const KeypressMessage &msg) {
+ MM1::Maps::Map43 &map = *static_cast<MM1::Maps::Map43 *>(g_maps->_currentMap);
+
+ if (_canAccept) {
+ if (msg.keycode == Common::KEYCODE_y) {
+ map.acceptQuest();
+
+ clearSurface();
+ writeString(0, 1, STRING["maps.map43.ironfist1"]);
+ writeString(0, 2, STRING[Common::String::format(
+ "maps.map43.quests.%d",
+ g_globals->_party[0]._quest)]);
+ close();
+
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ map.redrawGame();
+ }
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/lord_ironfist.h b/engines/mm/mm1/views/maps/lord_ironfist.h
new file mode 100644
index 00000000000..08912808737
--- /dev/null
+++ b/engines/mm/mm1/views/maps/lord_ironfist.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_LORD_IRONFIST_H
+#define MM1_VIEWS_MAPS_LORD_IRONFIST_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class LordIronfist : public TextView {
+private:
+ bool _canAccept;
+public:
+ LordIronfist();
+ virtual ~LordIronfist() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index bdcda9857e5..c4bdfab26e1 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -64,6 +64,7 @@ MODULE_OBJS := \
mm1/views/maps/inspectron.o \
mm1/views/maps/lion.o \
mm1/views/maps/lord_archer.o \
+ mm1/views/maps/lord_ironfist.o \
mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \
mm1/views/map/ruby.o \
Commit: 165c9c772fc45f403ce391e62e281a3bcf1d124b
https://github.com/scummvm/scummvm/commit/165c9c772fc45f403ce391e62e281a3bcf1d124b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:28+01:00
Commit Message:
MM: MM1: Added map 44
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map44.cpp
engines/mm/mm1/maps/map44.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/prisoners.cpp
engines/mm/mm1/views/maps/prisoners.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ae732c82234..959ff41db72 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -830,6 +830,7 @@ maps:
man: "MAN IN SHACKLES MOANS IN AGONY!\n\n"
cloaked: "A MYSTERIOUS CLOAKED FIGURE, BOUND AND\nGAGGED, LIES MOTIONLESS IN THE CORNER.\n\n"
demon: "A VICIOUS DEMON LUNGES AT THE PARTY,\nRESTRAINED ONLY BY A COLLAR AND CHAIN!\n\n"
+ mutated: "MUTATED CREATURE CHAINED TO THE FLOOR\nGRUNTS AS YOU APPROACH.\n\n"
options1: "OPTIONS: 1) SET THE PRISONER FREE.\n"
options2: "2) TORMENT THE PRISONER.\n"
options3: "3) LEAVE WITHOUT DISTURBING."
@@ -1427,3 +1428,11 @@ maps:
4: "FIND THE SHIPWRECK OF THE JOLLY RAVEN"
5: "DEFEAT THE PIRATE GHOST SHIP ANARCHIST"
6: "DEFEAT THE STRONGHOLD IN RAVENS WOOD"
+
+ map44:
+ exit: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ message_f: "ETCHED IN SILVER, MESSAGE F READS:\nTSTST,E1,D-DS15A1DRH"
+ clover: "THE GREEN CLOVER GRANTS THOSE WHO\nARE WORTHY +4 LUCK!"
+ fountain: "THE FABULOUS FABLED FOUNTAIN OF\nDRAGADUNE CONVERTS ALL GOLD INTO\nEXPERIENCE, ACCEPT (Y/N)?"
+ message: "CARVED IN STONE, A TRIVIAL MESSAGE\nREADS: I BE ME"
+ bones: "DECAYED BONES CRUNCH BENEATH YOU!"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index e81731aad10..a907a78aecf 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -175,7 +175,8 @@ enum CharFlags11 {
CHARFLAG11_GOT_INTELLIGENCE = 4,
CHARFLAG11_GOT_MIGHT = 8,
CHARFLAG11_GOT_ACCURACY = 0x10,
- CHARFLAG11_GOT_SPEED = 0x20
+ CHARFLAG11_GOT_SPEED = 0x20,
+ CHARFLAG11_GOT_LUCK = 0x40
};
enum CharFlags12 {
diff --git a/engines/mm/mm1/maps/map44.cpp b/engines/mm/mm1/maps/map44.cpp
index 8d0d0adb848..6545e9af604 100644
--- a/engines/mm/mm1/maps/map44.cpp
+++ b/engines/mm/mm1/maps/map44.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map44::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 11; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[62 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,79 @@ void Map44::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map44::special00() {
+ g_events->addView("MutatedPrisoner");
+}
+
+void Map44::special01() {
+ send(SoundMessage(
+ STRING["maps.map44.exit"],
+ []() {
+ g_maps->_mapPos = Common::Point(12, 12);
+ g_maps->changeMap(0x112, 2);
+ }
+ ));
+}
+
+void Map44::special02() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0xf05, 3);
+ }
+ ));
+}
+
+void Map44::special03() {
+ send(SoundMessage(STRING["maps.map44.message_f"]));
+}
+
+void Map44::special04() {
+ send(SoundMessage(STRING["maps.map44.clover"]));
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._flags[11] & CHARFLAG11_GOT_LUCK)) {
+ c._flags[11] |= CHARFLAG11_GOT_LUCK;
+ c._luck._current = c._luck._base = c._luck._base + 4;
+ }
+ }
+}
+
+void Map44::special05() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[5] |= CHARFLAG5_10;
+ }
+
+ send(SoundMessage(
+ STRING["maps.map44.fountain"],
+ []() {
+ Map44 &map = *static_cast<Map44 *>(g_maps->_currentMap);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._exp += c._gold;
+ c._gold = 0;
+ }
+
+ map.none160();
+ }
+ ));
+}
+
+void Map44::special06() {
+ send(SoundMessage(STRING["maps.map44.message"]));
+}
+
+void Map44::special07() {
+ send(SoundMessage(STRING["maps.map44.bones"]));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map44.h b/engines/mm/mm1/maps/map44.h
index e7403ab7ba1..0afa92b4b16 100644
--- a/engines/mm/mm1/maps/map44.h
+++ b/engines/mm/mm1/maps/map44.h
@@ -32,9 +32,26 @@ class Map44 : public Map {
typedef void (Map44:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
- const SpecialFn SPECIAL_FN[1] = {
- &Map44::special00
+ const SpecialFn SPECIAL_FN[11] = {
+ &Map44::special00,
+ &Map44::special01,
+ &Map44::special02,
+ &Map44::special03,
+ &Map44::special04,
+ &Map44::special05,
+ &Map44::special06,
+ &Map44::special07,
+ &Map44::special07,
+ &Map44::special07,
+ &Map44::special07
};
public:
Map44() : Map(44, "dragad", 0x107) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 727e9f69855..115a1978664 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -102,6 +102,7 @@ private:
Views::Maps::CloakedPrisoner _cloakedPrisoner;
Views::Maps::DemonPrisoner _demonPrisoner;
Views::Maps::ManPrisoner _manPrisoner;
+ Views::Maps::MutatedPrisoner _mutatedPrisoner;
Views::Maps::DogStatue _dogStatue;
Views::Maps::Ghost _ghost;
Views::Maps::Giant _giant;
diff --git a/engines/mm/mm1/views/maps/prisoners.cpp b/engines/mm/mm1/views/maps/prisoners.cpp
index b60666938fb..a88cfa5e02c 100644
--- a/engines/mm/mm1/views/maps/prisoners.cpp
+++ b/engines/mm/mm1/views/maps/prisoners.cpp
@@ -110,6 +110,11 @@ DemonPrisoner::DemonPrisoner() :
CHARFLAG1_10, EVIL, GOOD) {
}
+MutatedPrisoner::MutatedPrisoner() :
+ Prisoner("MutatedPrisoner", STRING["maps.prisoners.mutated"],
+ CHARFLAG1_2, GOOD, EVIL) {
+}
+
} // namespace Maps
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/maps/prisoners.h b/engines/mm/mm1/views/maps/prisoners.h
index 8e1fe3bdf92..d282c883733 100644
--- a/engines/mm/mm1/views/maps/prisoners.h
+++ b/engines/mm/mm1/views/maps/prisoners.h
@@ -71,6 +71,13 @@ public:
}
};
+class MutatedPrisoner : public Prisoner {
+public:
+ MutatedPrisoner();
+ virtual ~MutatedPrisoner() {
+ }
+};
+
} // namespace Maps
} // namespace Views
} // namespace MM1
Commit: 04097ea0704643785034560b1154e01552114934
https://github.com/scummvm/scummvm/commit/04097ea0704643785034560b1154e01552114934
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:28+01:00
Commit Message:
MM: MM1: Added map 45
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map45.cpp
engines/mm/mm1/maps/map45.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 959ff41db72..4e8d8550c18 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1436,3 +1436,13 @@ maps:
fountain: "THE FABULOUS FABLED FOUNTAIN OF\nDRAGADUNE CONVERTS ALL GOLD INTO\nEXPERIENCE, ACCEPT (Y/N)?"
message: "CARVED IN STONE, A TRIVIAL MESSAGE\nREADS: I BE ME"
bones: "DECAYED BONES CRUNCH BENEATH YOU!"
+
+ map45:
+ message8: "ETCHED IN GOLD, MESSAGE 8 READS:\nTHE-ARE-QUESTS,-INCREASES-IDENTIFY,-\nAPPLY.-LOCATIONS,-END-ATTAINED-MY-SEQUEL"
+ sign1: "PAINTED IN A BLACK AND WHITE PATTERN,\nA SIGN READS: THE LAST PART IS THE FIRST"
+ sign2: """TEMPLE WOLF PASS"""
+ sign3: """CULT OF THE NEW ORDER"""
+ walls: "THE WALLS GLOW OMINOUSLY"
+ message: "ETCHED IN STONE:\n""28 DAYS OUT. NO FOOD, LOW ON SUPPLIES.\nWE FEAR THE WORST YET WE CONTINUE-CORAK"
+ passage: "A CAVERNOUS PASSAGE, TAKE IT (Y/N)?"
+ wall: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
diff --git a/engines/mm/mm1/maps/map45.cpp b/engines/mm/mm1/maps/map45.cpp
index e7efb276dae..5185867736f 100644
--- a/engines/mm/mm1/maps/map45.cpp
+++ b/engines/mm/mm1/maps/map45.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map45::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 22; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[73 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,117 @@ void Map45::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map45::special00() {
+ send(SoundMessage(STRING["maps.map45.message8"]));
+}
+
+void Map45::special01() {
+ send(SoundMessage(
+ STRING["maps.map45.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(15, 12);
+ g_maps->changeMap(5, 1);
+ }
+ ));
+}
+
+void Map45::special02() {
+ special04();
+}
+
+void Map45::special03() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0x107, 1);
+ }
+ ));
+}
+
+void Map45::special04() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0xa00, 3);
+ }
+ ));
+}
+
+void Map45::special05() {
+ encounter(&_data[600], &_data[611]);
+}
+
+void Map45::special06() {
+ encounter(&_data[622], &_data[633]);
+}
+
+void Map45::special07() {
+ encounter(&_data[644], &_data[657]);
+}
+
+void Map45::special08() {
+ encounter(&_data[670], &_data[683]);
+}
+
+void Map45::special09() {
+ encounter(&_data[696], &_data[710]);
+}
+
+void Map45::special10() {
+ encounter(&_data[724], &_data[737]);
+}
+
+void Map45::special11() {
+ encounter(&_data[750], &_data[761]);
+}
+
+void Map45::special12() {
+ encounter(&_data[772], &_data[786]);
+}
+
+void Map45::special13() {
+ encounter(&_data[800], &_data[814]);
+}
+
+void Map45::special14() {
+ encounter(&_data[828], &_data[837]);
+}
+
+void Map45::special15() {
+ send(SoundMessage(STRING["maps.map45.sign1"]));
+}
+
+void Map45::special16() {
+ showSign(STRING["maps.map45.sign2"]);
+}
+
+void Map45::special18() {
+ showSign(STRING["maps.map45.sign3"]);
+}
+
+void Map45::special19() {
+ send(SoundMessage(STRING["maps.map45.walls"]));
+}
+
+void Map45::special20() {
+ send(SoundMessage(STRING["maps.map45.message"]));
+}
+
+void Map45::special21() {
+ send(SoundMessage(STRING["maps.map45.wall"]));
+}
+
+void Map45::showSign(const Common::String &line) {
+ send(SoundMessage(
+ 0, 1, STRING["maps.sign"],
+ 0, 2, line
+ ));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map45.h b/engines/mm/mm1/maps/map45.h
index 8c5aa06ae5d..85266c0a012 100644
--- a/engines/mm/mm1/maps/map45.h
+++ b/engines/mm/mm1/maps/map45.h
@@ -32,9 +32,51 @@ class Map45 : public Map {
typedef void (Map45:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special18();
+ void special19();
+ void special20();
+ void special21();
+ void showSign(const Common::String &line);
- const SpecialFn SPECIAL_FN[1] = {
- &Map45::special00
+ const SpecialFn SPECIAL_FN[22] = {
+ &Map45::special00,
+ &Map45::special01,
+ &Map45::special02,
+ &Map45::special03,
+ &Map45::special04,
+ &Map45::special05,
+ &Map45::special06,
+ &Map45::special07,
+ &Map45::special08,
+ &Map45::special09,
+ &Map45::special10,
+ &Map45::special11,
+ &Map45::special12,
+ &Map45::special13,
+ &Map45::special14,
+ &Map45::special15,
+ &Map45::special16,
+ &Map45::special16,
+ &Map45::special18,
+ &Map45::special19,
+ &Map45::special20,
+ &Map45::special21
};
public:
Map45() : Map(45, "udrag1", 0xF05) {}
Commit: 7fcdaa1125a2bd3b2ec397655b94342739bbd5d9
https://github.com/scummvm/scummvm/commit/7fcdaa1125a2bd3b2ec397655b94342739bbd5d9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:28+01:00
Commit Message:
MM: MM1: Added map 46
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map46.cpp
engines/mm/mm1/maps/map46.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 4e8d8550c18..33a059f12a4 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1446,3 +1446,8 @@ maps:
message: "ETCHED IN STONE:\n""28 DAYS OUT. NO FOOD, LOW ON SUPPLIES.\nWE FEAR THE WORST YET WE CONTINUE-CORAK"
passage: "A CAVERNOUS PASSAGE, TAKE IT (Y/N)?"
wall: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+
+ map46:
+ painted: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+ shakes: "THE GROUND SHAKES!"
+ clerics: "CLERICS OF THE SOUTH JUST BELOW-CORAK"
diff --git a/engines/mm/mm1/maps/map46.cpp b/engines/mm/mm1/maps/map46.cpp
index e6f3b2fe954..13532a373d4 100644
--- a/engines/mm/mm1/maps/map46.cpp
+++ b/engines/mm/mm1/maps/map46.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map46::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 7; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[58 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,49 @@ void Map46::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map46::special00() {
+ send(SoundMessage(STRING["maps.map46.painted"]));
+}
+
+void Map46::special01() {
+ send(SoundMessage(STRING["maps.map46.shakes"]));
+}
+
+void Map46::special02() {
+ send(SoundMessage(
+ STRING["maps.map46.painted"],
+ []() {
+ g_maps->changeMap(0x705, 3);
+ }
+ ));
+}
+
+void Map46::special03() {
+ send(SoundMessage(
+ STRING["maps.map46.painted"],
+ []() {
+ g_maps->changeMap(0xf05, 3);
+ }
+ ));
+}
+
+void Map46::special04() {
+ special03();
+}
+
+void Map46::special05() {
+ g_maps->_mapPos.x++;
+ updateGame();
+}
+
+void Map46::special06() {
+ send(SoundMessage(STRING["maps.map46.clerics"]));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map46.h b/engines/mm/mm1/maps/map46.h
index 4c5239c9c5c..66896ab4dea 100644
--- a/engines/mm/mm1/maps/map46.h
+++ b/engines/mm/mm1/maps/map46.h
@@ -32,9 +32,21 @@ class Map46 : public Map {
typedef void (Map46:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
- const SpecialFn SPECIAL_FN[1] = {
- &Map46::special00
+ const SpecialFn SPECIAL_FN[7] = {
+ &Map46::special00,
+ &Map46::special01,
+ &Map46::special02,
+ &Map46::special03,
+ &Map46::special04,
+ &Map46::special05,
+ &Map46::special06
};
public:
Map46() : Map(46, "udrag2", 0xA00) {}
Commit: 6406466488fd821bb4dd9fe90051c883de8acafc
https://github.com/scummvm/scummvm/commit/6406466488fd821bb4dd9fe90051c883de8acafc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:28+01:00
Commit Message:
MM: MM1: Fix treasure clearing on startup
Changed paths:
engines/mm/mm1/globals.cpp
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index f4bbccec6a3..c49706c9255 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -32,7 +32,7 @@ Globals *g_globals;
Globals::Globals() {
g_globals = this;
- Common::fill(&_treasure[0], &_treasure[TREASURE_COUNT], 0);
+ _treasure.clear();
}
Globals::~Globals() {
Commit: 284bed8afa6fb360c36802d30693f3f23e8d70e4
https://github.com/scummvm/scummvm/commit/284bed8afa6fb360c36802d30693f3f23e8d70e4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:28+01:00
Commit Message:
MM: MM1: Added map 47
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map47.cpp
engines/mm/mm1/maps/map47.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 33a059f12a4..08134d91727 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1451,3 +1451,17 @@ maps:
painted: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
shakes: "THE GROUND SHAKES!"
clerics: "CLERICS OF THE SOUTH JUST BELOW-CORAK"
+
+ map47:
+ message5: "ETCHED IN GOLD, MESSAGE 5 READS:\nSCOOP:-THE-DISCOVERIES-YOUR-TO-RETURN-\nTHE-YOUR-FOR-DREAMS-IS"
+ gong: "COVERED WITH CRYPTIC SYMBOLS, A LARGE\nBRASS GONG HANGS FROM THE CEILING.\nSTRIKE IT (Y/N)?"
+ tones:
+ 0: "A LOUD TONE RESOUNDS\nTHROUGHOUT THE ROOM!"
+ 1: "A SHARP TONE ASSAULTS YOUR SENSES!"
+ 2: "A MELLOW TONE RELAXES YOU."
+ clerics1: "THE CLERICS OF THE SOUTH SPEAK:\n"
+ clerics2: """HEAR THE 3 TONES AND RETURN!"""
+ clerics3: """WE DEEM YOU WORTHY OF ADVANCEMENT!"""
+ poof: "POOF!"
+ painting: "ON THE RIGHT WALL IS A PAINTING OF A\nBOX,ON THE LEFT A PAINTING OF A CURTAIN."
+ door_number: "DOOR NUMBER %c"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index a907a78aecf..5e30be0be94 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -176,7 +176,8 @@ enum CharFlags11 {
CHARFLAG11_GOT_MIGHT = 8,
CHARFLAG11_GOT_ACCURACY = 0x10,
CHARFLAG11_GOT_SPEED = 0x20,
- CHARFLAG11_GOT_LUCK = 0x40
+ CHARFLAG11_GOT_LUCK = 0x40,
+ CHARFLAG11_CLERICS = 0x80
};
enum CharFlags12 {
diff --git a/engines/mm/mm1/maps/map47.cpp b/engines/mm/mm1/maps/map47.cpp
index 1c8dbadadd3..31afeebf87b 100644
--- a/engines/mm/mm1/maps/map47.cpp
+++ b/engines/mm/mm1/maps/map47.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define ARRAY1 250
+
void Map47::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 26; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[77 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,132 @@ void Map47::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ if (getRandomNumber(100) < 10) {
+ g_globals->_encounters.execute();
+
+ } else {
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(16) - 1, getRandomNumber(16) - 1);
+ updateGame();
+ send(SoundMessage(STRING["maps.map47.poof"]));
+ }
}
void Map47::special00() {
+ send(SoundMessage(STRING["maps.map47.message5"]));
+}
+
+void Map47::special01() {
+ send(SoundMessage(
+ STRING["maps.map47.gong"],
+ []() {
+ Map47 &map = *static_cast<Map47 *>(g_maps->_currentMap);
+ int toneNum = getRandomNumber(6);
+ if (toneNum < 4) {
+ g_events->send(SoundMessage(STRING[
+ Common::String::format("maps.map47.tones.%d", toneNum)]));
+ } else {
+ map.poof();
+ }
+ }
+ ));
+}
+
+void Map47::special02() {
+ if (_data[ARRAY1] && _data[ARRAY1 + 1] && _data[ARRAY1 + 2]) {
+ send(SoundMessage(STRING["maps.map47.clerics3"]));
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[11] = CHARFLAG11_CLERICS;
+ }
+ }
+}
+
+void Map47::special03() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0xa00, 3);
+ }
+ ));
+}
+
+void Map47::special04() {
+ send(SoundMessage(STRING["maps.map47.painting"]));
+}
+
+void Map47::special05() {
+ encounter(&_data[587], &_data[594]);
+}
+
+void Map47::special06() {
+ encounter(&_data[601], &_data[608]);
+}
+
+void Map47::special07() {
+ encounter(&_data[615], &_data[624]);
+}
+
+void Map47::special08() {
+ encounter(&_data[633], &_data[644]);
+}
+
+void Map47::special09() {
+ encounter(&_data[655], &_data[665]);
+}
+
+void Map47::special10() {
+ encounter(&_data[675], &_data[684]);
+}
+
+void Map47::special11() {
+ encounter(&_data[693], &_data[700]);
+}
+
+void Map47::special12() {
+ encounter(&_data[707], &_data[718]);
+}
+
+void Map47::special13() {
+ encounter(&_data[729], &_data[740]);
+}
+
+void Map47::special14() {
+ encounter(&_data[751], &_data[762]);
+}
+
+void Map47::special15() {
+ encounter(&_data[773], &_data[782]);
+}
+
+void Map47::special16() {
+ encounter(&_data[791], &_data[801]);
+}
+
+void Map47::special17() {
+ encounter(&_data[811], &_data[821]);
+}
+
+void Map47::special23() {
+ Common::String line = Common::String::format(
+ STRING["maps.map47.door_number"].c_str(),
+ '0' + (g_maps->_mapPos.x - 5)
+ );
+ send(SoundMessage(line));
+}
+
+void Map47::poof() {
+ if (getRandomNumber(100) < 10) {
+ g_globals->_encounters.execute();
+
+ } else {
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(16) - 1, getRandomNumber(16) - 1);
+ updateGame();
+
+ send(SoundMessage(STRING["maps.map47.poof"]));
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map47.h b/engines/mm/mm1/maps/map47.h
index 5b863168c2c..9625ec3c884 100644
--- a/engines/mm/mm1/maps/map47.h
+++ b/engines/mm/mm1/maps/map47.h
@@ -32,9 +32,52 @@ class Map47 : public Map {
typedef void (Map47:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special17();
+ void special23();
- const SpecialFn SPECIAL_FN[1] = {
- &Map47::special00
+ const SpecialFn SPECIAL_FN[26] = {
+ &Map47::special00,
+ &Map47::special01,
+ &Map47::special02,
+ &Map47::special03,
+ &Map47::special04,
+ &Map47::special05,
+ &Map47::special06,
+ &Map47::special07,
+ &Map47::special08,
+ &Map47::special09,
+ &Map47::special10,
+ &Map47::special11,
+ &Map47::special12,
+ &Map47::special13,
+ &Map47::special14,
+ &Map47::special15,
+ &Map47::special16,
+ &Map47::special17,
+ &Map47::special01,
+ &Map47::special01,
+ &Map47::special01,
+ &Map47::special01,
+ &Map47::special01,
+ &Map47::special23,
+ &Map47::special23,
+ &Map47::special23
};
public:
Map47() : Map(47, "udrag3", 0x705) {}
@@ -43,6 +86,8 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ void poof();
};
} // namespace Maps
Commit: 0e6b445c987ff890da780ec817c676f83efb9b09
https://github.com/scummvm/scummvm/commit/0e6b445c987ff890da780ec817c676f83efb9b09
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:29+01:00
Commit Message:
MM: MM1: Added map 48, fixed some answer entry views' rendering
Changed paths:
A engines/mm/mm1/views/maps/orango.cpp
A engines/mm/mm1/views/maps/orango.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map48.cpp
engines/mm/mm1/maps/map48.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/chess.cpp
engines/mm/mm1/views/maps/ice_princess.cpp
engines/mm/mm1/views/maps/lion.cpp
engines/mm/mm1/views/maps/ruby.cpp
engines/mm/mm1/views/maps/trivia.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 08134d91727..469e8228f38 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1465,3 +1465,8 @@ maps:
poof: "POOF!"
painting: "ON THE RIGHT WALL IS A PAINTING OF A\nBOX,ON THE LEFT A PAINTING OF A CURTAIN."
door_number: "DOOR NUMBER %c"
+
+ map48:
+ orango1: "A STRANGE ALIEN BEING IN A SHIMMERING\nSILVER JUMPSUIT PROCLAIMS, ""THIS IS A\nSOUL MAZE AND YOU ARE ITS PRISONER!\nTO ESCAPE, YOU MUST FIND YOUR CAPTOR'S\nNAME HIDDEN WITHIN THESE WALLS.""\n\nANSWER:> ..............."
+ orango2: "KEEP LOOKING!"
+ orango3: "AGENT ORANGO SEVENTEEN REPORTING:\nIMPOSTER XX21A7-3 VOIDED!\nSTARPHASE 5281.6 AT 120-VARN-161 POD #41YOU ARE NOW RANK 1 AND ELIGIBLE FOR\nTRANSFER. FIND INNER SANCTUM FOR NEW\nASSIGNMENT. THE WALLS BEGIN TO FADE...\n(PRESS SPACE)"
diff --git a/engines/mm/mm1/maps/map48.cpp b/engines/mm/mm1/maps/map48.cpp
index a34a6f2aceb..19948effa57 100644
--- a/engines/mm/mm1/maps/map48.cpp
+++ b/engines/mm/mm1/maps/map48.cpp
@@ -30,28 +30,7 @@ namespace MM1 {
namespace Maps {
void Map48::special() {
- // Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
- if (g_maps->_mapOffset == _data[51 + i]) {
- // Found a specially handled cell, but it
- // only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
- (this->*SPECIAL_FN[i])();
- } else {
- checkPartyDead();
- }
- return;
- }
- }
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
-}
-
-void Map48::special00() {
+ g_events->addView("Orango");
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map48.h b/engines/mm/mm1/maps/map48.h
index 8910178103c..d51c3c7963f 100644
--- a/engines/mm/mm1/maps/map48.h
+++ b/engines/mm/mm1/maps/map48.h
@@ -30,12 +30,6 @@ namespace Maps {
class Map48 : public Map {
typedef void (Map48:: *SpecialFn)();
-private:
- void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map48::special00
- };
public:
Map48() : Map(48, "demon", 0x412) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 115a1978664..372cf0cc9b4 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -54,6 +54,7 @@
#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/lord_archer.h"
#include "mm/mm1/views/maps/lord_ironfist.h"
+#include "mm/mm1/views/maps/orango.h"
#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/views/maps/resistances.h"
#include "mm/mm1/views/maps/ruby.h"
@@ -111,6 +112,7 @@ private:
Views::Maps::Lion _lion;
Views::Maps::LordArcher _lordArcher;
Views::Maps::LordIronfist _lordIronfist;
+ Views::Maps::Orango _orango;
Views::Maps::Resistances _resistances;
Views::Maps::Ruby _ruby;
Views::Maps::Trivia _trivia;
diff --git a/engines/mm/mm1/views/maps/chess.cpp b/engines/mm/mm1/views/maps/chess.cpp
index e2ea109f845..803aa612fba 100644
--- a/engines/mm/mm1/views/maps/chess.cpp
+++ b/engines/mm/mm1/views/maps/chess.cpp
@@ -44,6 +44,7 @@ bool Chess::msgFocus(const FocusMessage &msg) {
void Chess::draw() {
clearSurface();
writeString(0, 0, STRING["maps.map29.chess"]);
+ AnswerEntry::draw();
}
void Chess::answerEntered() {
diff --git a/engines/mm/mm1/views/maps/ice_princess.cpp b/engines/mm/mm1/views/maps/ice_princess.cpp
index 8dc46cc4496..f1bf199b9ed 100644
--- a/engines/mm/mm1/views/maps/ice_princess.cpp
+++ b/engines/mm/mm1/views/maps/ice_princess.cpp
@@ -40,6 +40,7 @@ IcePrincess::IcePrincess() :
void IcePrincess::draw() {
clearSurface();
writeString(0, 1, STRING["maps.map19.ice_princess"]);
+ AnswerEntry::draw();
}
void IcePrincess::answerEntered() {
diff --git a/engines/mm/mm1/views/maps/lion.cpp b/engines/mm/mm1/views/maps/lion.cpp
index a5016ac8ea0..2e787f62953 100644
--- a/engines/mm/mm1/views/maps/lion.cpp
+++ b/engines/mm/mm1/views/maps/lion.cpp
@@ -37,6 +37,7 @@ Lion::Lion() : AnswerEntry("Lion", Common::Point(11, 2), 10) {
void Lion::draw() {
clearSurface();
writeString(0, 1, STRING["maps.map32.statue"]);
+ AnswerEntry::draw();
}
void Lion::answerEntered() {
diff --git a/engines/mm/mm1/views/maps/orango.cpp b/engines/mm/mm1/views/maps/orango.cpp
new file mode 100644
index 00000000000..4ee418169d2
--- /dev/null
+++ b/engines/mm/mm1/views/maps/orango.cpp
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/orango.h"
+#include "mm/mm1/maps/map48.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define ANSWER_OFFSET 274
+
+Orango::Orango() :
+ AnswerEntry("Orango", Common::Point(9, 6), 15) {
+ _bounds = getLineBounds(17, 24);
+}
+
+void Orango::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map48.orango1"]);
+ AnswerEntry::draw();
+}
+
+void Orango::answerEntered() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Common::String properAnswer;
+ close();
+
+ for (int i = 0; i < 15 && map[ANSWER_OFFSET + i]; ++i)
+ properAnswer += map[ANSWER_OFFSET + i] & 0x7f + 29;
+
+ if (_answer == properAnswer) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[13] |= CHARFLAG13_40;
+ }
+
+ g_maps->_mapPos = Common::Point(8, 5);
+ g_maps->changeMap(0x604, 1);
+ g_events->send(SoundMessage(STRING["maps.map48.orango3"]));
+
+ } else {
+ g_maps->_mapPos.x++;
+ map.updateGame();
+ g_events->send(SoundMessage(13, 2, STRING["maps.map48.orango2"]));
+ }
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/orango.h b/engines/mm/mm1/views/maps/orango.h
new file mode 100644
index 00000000000..527be8630f3
--- /dev/null
+++ b/engines/mm/mm1/views/maps/orango.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_ORANGO_H
+#define MM1_VIEWS_MAPS_ORANGO_H
+
+#include "mm/mm1/views/maps/answer_entry.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Orango : public AnswerEntry {
+protected:
+ void answerEntered() override;
+
+public:
+ Orango();
+ virtual ~Orango() {}
+
+ void draw() override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/maps/ruby.cpp b/engines/mm/mm1/views/maps/ruby.cpp
index d0619f9f879..23af5b1b094 100644
--- a/engines/mm/mm1/views/maps/ruby.cpp
+++ b/engines/mm/mm1/views/maps/ruby.cpp
@@ -37,6 +37,7 @@ Ruby::Ruby() : AnswerEntry("Ruby", Common::Point(2, 9), 12) {
void Ruby::draw() {
clearSurface();
writeString(0, 1, STRING["maps.map39.ruby1"]);
+ AnswerEntry::draw();
}
void Ruby::answerEntered() {
diff --git a/engines/mm/mm1/views/maps/trivia.cpp b/engines/mm/mm1/views/maps/trivia.cpp
index 1355f8a3f41..ea590afe979 100644
--- a/engines/mm/mm1/views/maps/trivia.cpp
+++ b/engines/mm/mm1/views/maps/trivia.cpp
@@ -49,6 +49,7 @@ bool Trivia::msgValue(const ValueMessage &msg) {
void Trivia::draw() {
clearSurface();
writeString(0, 1, STRING["maps.map19.ice_princess"]);
+ AnswerEntry::draw();
}
void Trivia::answerEntered() {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c4bdfab26e1..d0101095f2e 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -65,6 +65,7 @@ MODULE_OBJS := \
mm1/views/maps/lion.o \
mm1/views/maps/lord_archer.o \
mm1/views/maps/lord_ironfist.o \
+ mm1/views/maps/orango.o \
mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \
mm1/views/map/ruby.o \
Commit: f16eb6b24597a5350647ef4dd8a885b7904778dc
https://github.com/scummvm/scummvm/commit/f16eb6b24597a5350647ef4dd8a885b7904778dc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:29+01:00
Commit Message:
MM: MM1: gcc compilation fixes
Changed paths:
engines/mm/mm1/views/maps/chess.cpp
engines/mm/mm1/views/maps/ice_princess.cpp
engines/mm/mm1/views/maps/orango.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/maps/chess.cpp b/engines/mm/mm1/views/maps/chess.cpp
index 803aa612fba..0db7db6960f 100644
--- a/engines/mm/mm1/views/maps/chess.cpp
+++ b/engines/mm/mm1/views/maps/chess.cpp
@@ -58,7 +58,7 @@ void Chess::answerEntered() {
InfoMessage msg(
16, 2, STRING["maps.map19.correct"],
[]() {
- MM1::Maps::Map29 &map = *static_cast<MM1::Maps::Map29 *>(g_maps->_currentMap);
+ MM1::Maps::Map29 &map29 = *static_cast<MM1::Maps::Map29 *>(g_maps->_currentMap);
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
@@ -66,7 +66,7 @@ void Chess::answerEntered() {
}
g_maps->_mapPos.y = 7;
- map.updateGame();
+ map29.updateGame();
}
);
diff --git a/engines/mm/mm1/views/maps/ice_princess.cpp b/engines/mm/mm1/views/maps/ice_princess.cpp
index f1bf199b9ed..03a9cff4ef3 100644
--- a/engines/mm/mm1/views/maps/ice_princess.cpp
+++ b/engines/mm/mm1/views/maps/ice_princess.cpp
@@ -50,7 +50,7 @@ void IcePrincess::answerEntered() {
close();
for (int i = 0; i < 4; ++i)
- properAnswer += map[ANSWER_OFFSET + i] & 0x7f - 64;
+ properAnswer += (map[ANSWER_OFFSET + i] & 0x7f) - 64;
if (_answer == properAnswer) {
InfoMessage msg(
diff --git a/engines/mm/mm1/views/maps/orango.cpp b/engines/mm/mm1/views/maps/orango.cpp
index 4ee418169d2..c2883b9b9c3 100644
--- a/engines/mm/mm1/views/maps/orango.cpp
+++ b/engines/mm/mm1/views/maps/orango.cpp
@@ -48,7 +48,7 @@ void Orango::answerEntered() {
close();
for (int i = 0; i < 15 && map[ANSWER_OFFSET + i]; ++i)
- properAnswer += map[ANSWER_OFFSET + i] & 0x7f + 29;
+ properAnswer += (map[ANSWER_OFFSET + i] & 0x7f) + 29;
if (_answer == properAnswer) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index d0101095f2e..7c37f1246f0 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -68,7 +68,7 @@ MODULE_OBJS := \
mm1/views/maps/orango.o \
mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \
- mm1/views/map/ruby.o \
+ mm1/views/maps/ruby.o \
mm1/views/maps/trivia.o \
mm1/views/maps/volcano_god.o \
mm1/views/maps/won_game.o \
Commit: e3581b594aac75372832aec30c346bf929782a29
https://github.com/scummvm/scummvm/commit/e3581b594aac75372832aec30c346bf929782a29
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:29+01:00
Commit Message:
MM: MM1: More compilation fixes
Changed paths:
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/views/maps/volcano_god.cpp
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index 4c4f6dd54a6..4bef007ab10 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -216,9 +216,9 @@ void Map09::portal(int index) {
send(SoundMessage(
STRING["maps.map09.portal"],
[]() {
- int index = static_cast<Map09 *>(g_maps->_currentMap)->_portalIndex;
- g_maps->_mapPos = Common::Point(MAP_DEST_X[index], MAP_DEST_Y[index]);
- g_maps->changeMap(MAP_DEST_ID[index], 1);
+ int idx = static_cast<Map09 *>(g_maps->_currentMap)->_portalIndex;
+ g_maps->_mapPos = Common::Point(MAP_DEST_X[idx], MAP_DEST_Y[idx]);
+ g_maps->changeMap(MAP_DEST_ID[idx], 1);
}
));
}
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 18449f8d677..d8c67e94f39 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -112,10 +112,9 @@ void Map17::askQuestion(uint partyIndex) {
}
_data[VAL1] = partyIndex;
- Character &c = g_globals->_party[partyIndex];
- g_globals->_currCharacter = &c;
+ g_globals->_currCharacter = &g_globals->_party[partyIndex];
- if (!(c._condition & BAD_CONDITION)) {
+ if (!(g_globals->_currCharacter->_condition & BAD_CONDITION)) {
InfoMessage msg(
0, 0, STRING["maps.map17.color"],
0, 2, STRING["maps.map17.options"],
@@ -125,16 +124,16 @@ void Map17::askQuestion(uint partyIndex) {
ks.keycode <= Common::KEYCODE_9) {
map[VAL2] = ks.ascii - '1';
- Common::String msg;
+ Common::String line;
Character &c = *g_globals->_currCharacter;
int val = c._flags[2] & 0xf;
if (!val || (val & 7) != map[VAL2]) {
c._condition = ERADICATED;
- msg = STRING["maps.map17.wrong"];
+ line = STRING["maps.map17.wrong"];
} else {
map[VAL3]++;
c._flags[4] |= CHARFLAG4_80;
- msg = STRING["maps.map17.correct"];
+ line = STRING["maps.map17.correct"];
}
Sound::sound(SOUND_3);
@@ -143,10 +142,10 @@ void Map17::askQuestion(uint partyIndex) {
msg2._delaySeconds = 1;
msg2._lines.push_back(Line(0, 0, STRING["maps.map17.color"]));
msg2._lines.push_back(Line(0, 2, STRING["maps.map17.options"]));
- msg2._lines.push_back(Line(16, 5, msg));
+ msg2._lines.push_back(Line(16, 5, line));
msg2._ynCallback = []() {
- Map17 &map = *static_cast<Map17 *>(g_maps->_currentMap);
- map.askQuestion(map[VAL1] + 1);
+ Map17 &map17 = *static_cast<Map17 *>(g_maps->_currentMap);
+ map17.askQuestion(map17[VAL1] + 1);
};
g_events->send(msg2);
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index 3f6e9e92bac..84a08b468ea 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -30,8 +30,6 @@ namespace MM1 {
namespace Maps {
void Map25::special() {
- Game::Encounter &enc = g_globals->_encounters;
-
// Scan for special actions on the map cell
for (uint i = 0; i < 3; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
@@ -49,6 +47,7 @@ void Map25::special() {
switch (_states[g_maps->_mapOffset]) {
case 0:
if (getRandomNumber(100) == 100) {
+ Game::Encounter &enc = g_globals->_encounters;
Character &c = g_globals->_party[0];
g_globals->_currCharacter = &c;
int val = getRandomNumber((c._level >= 12 ? 14 : c._level) + 2);
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
index 7ce3622cdde..fb3b3ab6ff9 100644
--- a/engines/mm/mm1/views/maps/volcano_god.cpp
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -72,6 +72,7 @@ bool VolcanoGod::msgKeypress(const KeypressMessage &msg) {
default:
break;
}
+ break;
case ENTER_RESPONSE:
return AnswerEntry::msgKeypress(msg);
Commit: 780708535957c2c00c310c5aca2ca1331aa5ef46
https://github.com/scummvm/scummvm/commit/780708535957c2c00c310c5aca2ca1331aa5ef46
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:29+01:00
Commit Message:
MM: MM1: Added map 49
Changed paths:
A engines/mm/mm1/views/maps/alamar.cpp
A engines/mm/mm1/views/maps/alamar.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map34.cpp
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map49.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/orango.cpp
engines/mm/mm1/views/maps/prisoners.cpp
engines/mm/mm1/views/maps/prisoners.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 469e8228f38..c99ab62b7e0 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -831,6 +831,7 @@ maps:
cloaked: "A MYSTERIOUS CLOAKED FIGURE, BOUND AND\nGAGGED, LIES MOTIONLESS IN THE CORNER.\n\n"
demon: "A VICIOUS DEMON LUNGES AT THE PARTY,\nRESTRAINED ONLY BY A COLLAR AND CHAIN!\n\n"
mutated: "MUTATED CREATURE CHAINED TO THE FLOOR\nGRUNTS AS YOU APPROACH.\n\n"
+ maiden: "INSIDE A STEEL CAGE,A FAIR MAIDEN WEEPS.\n\n"
options1: "OPTIONS: 1) SET THE PRISONER FREE.\n"
options2: "2) TORMENT THE PRISONER.\n"
options3: "3) LEAVE WITHOUT DISTURBING."
@@ -1470,3 +1471,19 @@ maps:
orango1: "A STRANGE ALIEN BEING IN A SHIMMERING\nSILVER JUMPSUIT PROCLAIMS, ""THIS IS A\nSOUL MAZE AND YOU ARE ITS PRISONER!\nTO ESCAPE, YOU MUST FIND YOUR CAPTOR'S\nNAME HIDDEN WITHIN THESE WALLS.""\n\nANSWER:> ..............."
orango2: "KEEP LOOKING!"
orango3: "AGENT ORANGO SEVENTEEN REPORTING:\nIMPOSTER XX21A7-3 VOIDED!\nSTARPHASE 5281.6 AT 120-VARN-161 POD #41YOU ARE NOW RANK 1 AND ELIGIBLE FOR\nTRANSFER. FIND INNER SANCTUM FOR NEW\nASSIGNMENT. THE WALLS BEGIN TO FADE...\n(PRESS SPACE)"
+
+ map49:
+ chute: "A CHUTE..."
+ catapult: "A CATAPULT EJECTS YOU FROM THE TOWER!"
+ passage: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ message_e: "ETCHED IN SILVER, MESSAGE E READS:\nOEI/:1-33-1EK5;D-ET,"
+ alamar1: "THE OMNIPOTENT KING ALAMAR SPEAKS,\n\n"
+ alamar2: """VARNLINGS, I QUEST THEE TO FIND THE\nCRYPT OF CARMENCA. AWAY WITH YOU..."""
+ alamar3: """MY SAVIORS, YOU'RE ALWAYS WELCOME HERE!\nYOU SHOULD FIND THE INNER SANCTUM...\nLIVE LONG AND PROSPER."""
+ alamar4: """YOU'VE DISCOVERED MY TRUE IDENTITY!\nINTO THE SOUL MAZE YOU GO..."""
+ guards1: "CASTLE GUARDS EXCLAIM,\n""NO MERCHANTS PASS! BEGONE PEASANTS."""
+ guards2: "KINGS GUARDS APPROACH.\n""NO KING'S PASS, NO ADMITTANCE!"""
+ scream: "A LOUD SCREAM FROM BEHIND THE DOOR!"
+ trap: "SINGE! ACID TRAP."
+ explosion: "BOOM! A FIERY EXPLOSION."
+ throne_room: "THRONE ROOM"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 5e30be0be94..1dde59a674b 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -198,7 +198,7 @@ enum CharFlags13 {
CHARFLAG13_8 = 8,
CHARFLAG13_10 = 0x10,
CHARFLAG13_20 = 0x20,
- CHARFLAG13_40 = 0x40,
+ CHARFLAG13_ALAMAR = 0x40,
CHARFLAG13_80 = 0x80
};
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 6a5bf97d9dd..81c0bcff246 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -37,6 +37,7 @@ enum ItemId {
BELLADONNA_ID = 177,
VELLUM_SCROLL_ID = 231,
RUBY_WHISTLE_ID = 232,
+ KINGS_PASS_ID = 233,
MERCHANTS_PASS_ID = 234,
CORAL_KEY_ID = 236,
BRONZE_KEY_ID = 237,
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index e5001fcffe6..67857ea1504 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -72,6 +72,8 @@ enum DataOffset {
MAP_36 = 36,
MAP_37 = 37,
MAP_DISPEL_THRESHOLD = 38,
+ MAP_SURFACE_ID = 39,
+ MAP_SURFACE_SECTION = 41,
MAP_SURFACE_X = 42,
MAP_SURFACE_Y = 43,
MAP_44 = 44,
diff --git a/engines/mm/mm1/maps/map34.cpp b/engines/mm/mm1/maps/map34.cpp
index 2f68914ebc6..e3422d8e123 100644
--- a/engines/mm/mm1/maps/map34.cpp
+++ b/engines/mm/mm1/maps/map34.cpp
@@ -68,7 +68,7 @@ void Map34::special01() {
void Map34::special02() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- if ((c._flags[13] & CHARFLAG13_40) || c.hasItem(EYE_OF_GOROS_ID)) {
+ if ((c._flags[13] & CHARFLAG13_ALAMAR) || c.hasItem(EYE_OF_GOROS_ID)) {
g_maps->clearSpecial();
g_globals->_encounters.execute();
return;
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index f6bcc7f6444..e6212b68a5e 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -29,14 +29,16 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 952
+#define VAL2 154
+
void Map49::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 23; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[74 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +46,118 @@ void Map49::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map49::special00() {
+ g_events->addView("MaidenPrisoner");
+}
+
+void Map49::special01() {
+ send(SoundMessage(
+ STRING["maps.map49.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(14, 7);
+ g_maps->changeMap(0xb1a, 2);
+ }
+ ));
+}
+
+void Map49::special02() {
+ g_maps->_mapPos = Common::Point(15, 7);
+ g_maps->changeMap(0xb1a, 2);
+ send(SoundMessage(STRING["maps.map49.chute"]));
+}
+
+void Map49::special03() {
+ send(SoundMessage(STRING["maps.map49.message_e"]));
+}
+
+void Map49::special04() {
+ if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
+ g_maps->_mapPos = Common::Point(
+ _data[MAP_SURFACE_X], _data[MAP_SURFACE_Y]);
+ g_maps->changeMap(
+ READ_LE_UINT16(&_data[MAP_SURFACE_ID]),
+ _data[MAP_SURFACE_SECTION]
+ );
+
+ send(SoundMessage(STRING["maps.map49.guards2"]));
+ }
+}
+
+void Map49::special05() {
+ if (!g_globals->_party.hasItem(KINGS_PASS_ID)) {
+ g_maps->_mapPos.x++;
+ updateGame();
+ send(SoundMessage(STRING["maps.map49.guards2"]));
+
+ } else {
+ checkPartyDead();
+ }
+}
+
+void Map49::special06() {
+ if (_data[VAL1]) {
+ g_maps->_mapPos = Common::Point(6, 0);
+ g_maps->changeMap(0x412, 3);
+
+ } else {
+ send("GameView", DrawMonsterMessage(7));
+ g_events->addView("Alamar");
+ }
+}
+
+void Map49::special07() {
+ reduceHP();
+ reduceHP();
+ g_maps->_mapPos = Common::Point(4, 7);
+ g_maps->changeMap(0xb1a, 2);
+
+ send(SoundMessage(STRING["maps.map49.catapult"]));
+}
+
+void Map49::special08() {
+ if (!g_globals->_activeSpells._s.fire)
+ reduceHP();
+ reduceHP();
+
+ messageEncounter(STRING["maps.map49.trap"]);
+}
+
+void Map49::special09() {
+ if (!g_globals->_activeSpells._s.acid)
+ reduceHP();
+ reduceHP();
+
+ messageEncounter(STRING["maps.map49.explosion"]);
+}
+
+void Map49::special16() {
+ send(SoundMessage(STRING["maps.map49.scream"]));
+}
+
+void Map49::special20() {
+ g_globals->_treasure[7] = 46;
+ g_globals->_treasure[6] = 224;
+ g_events->addAction(KEYBIND_SEARCH);
+}
+
+void Map49::special22() {
+ send(SoundMessage(STRING["maps.map49.throne_room"]));
+}
+
+void Map49::messageEncounter(const Common::String &line) {
+ SoundMessage msg(line,
+ []() {
+ g_globals->_encounters.execute();
+ }
+ );
+ msg._delaySeconds = 4;
+ send(msg);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map49.h b/engines/mm/mm1/maps/map49.h
index fd9e2760a80..042f02ecd0c 100644
--- a/engines/mm/mm1/maps/map49.h
+++ b/engines/mm/mm1/maps/map49.h
@@ -32,9 +32,44 @@ class Map49 : public Map {
typedef void (Map49:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special16();
+ void special20();
+ void special22();
+ void messageEncounter(const Common::String &line);
- const SpecialFn SPECIAL_FN[1] = {
- &Map49::special00
+ const SpecialFn SPECIAL_FN[23] = {
+ &Map49::special00,
+ &Map49::special01,
+ &Map49::special02,
+ &Map49::special03,
+ &Map49::special04,
+ &Map49::special05,
+ &Map49::special06,
+ &Map49::special07,
+ &Map49::special08,
+ &Map49::special09,
+ &Map49::special08,
+ &Map49::special09,
+ &Map49::special08,
+ &Map49::special09,
+ &Map49::special08,
+ &Map49::special09,
+ &Map49::special16,
+ &Map49::special16,
+ &Map49::special08,
+ &Map49::special09,
+ &Map49::special20,
+ &Map49::special20,
+ &Map49::special22
};
public:
Map49() : Map(49, "alamar", 0xB07) {}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 372cf0cc9b4..02420b05519 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -43,6 +43,7 @@
#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
+#include "mm/mm1/views/maps/alamar.h"
#include "mm/mm1/views/maps/alien.h"
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
@@ -96,12 +97,14 @@ private:
Views::Locations::Temple _temple;
Views::Locations::Training _training;
+ Views::Maps::Alamar _alamar;
Views::Maps::Alien _alien;
Views::Maps::Arrested _arrested;
Views::Maps::Chess _chess;
Views::Maps::ChildPrisoner _childPrisoner;
Views::Maps::CloakedPrisoner _cloakedPrisoner;
Views::Maps::DemonPrisoner _demonPrisoner;
+ Views::Maps::MaidenPrisoner _maidenPrisoner;
Views::Maps::ManPrisoner _manPrisoner;
Views::Maps::MutatedPrisoner _mutatedPrisoner;
Views::Maps::DogStatue _dogStatue;
diff --git a/engines/mm/mm1/views/maps/alamar.cpp b/engines/mm/mm1/views/maps/alamar.cpp
new file mode 100644
index 00000000000..bc1df7b77dd
--- /dev/null
+++ b/engines/mm/mm1/views/maps/alamar.cpp
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/alamar.h"
+#include "mm/mm1/maps/map49.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define VAL1 952
+#define HAS_EYE 154
+
+Alamar::Alamar() : TextView("Alamar") {
+ _bounds = getLineBounds(17, 24);
+}
+
+bool Alamar::msgFocus(const FocusMessage &msg) {
+ MM1::Maps::Map49 &map = *static_cast<MM1::Maps::Map49 *>(g_maps->_currentMap);
+
+ _succeeded = false;
+ for (uint i = 0; i < g_globals->_party.size() && !_succeeded; ++i)
+ _succeeded = (g_globals->_party[i]._flags[13] & CHARFLAG13_ALAMAR) != 0;
+ map[HAS_EYE] = g_globals->_party.hasItem(EYE_OF_GOROS_ID) ? 1 : 0;
+
+ if (!_succeeded && !map[HAS_EYE]) {
+ for (uint i = 0; i < g_globals->_party.size() && !_succeeded; ++i)
+ g_globals->_party[i]._quest = 255;
+ }
+
+ Sound::sound(SOUND_2);
+ Sound::sound(SOUND_2);
+
+ return TextView::msgFocus(msg);
+}
+
+void Alamar::draw() {
+ MM1::Maps::Map49 &map = *static_cast<MM1::Maps::Map49 *>(g_maps->_currentMap);
+
+ if (_succeeded) {
+ clearSurface();
+ writeString(0, 0, STRING["maps.map49.alamar1"]);
+ writeString(STRING["maps.map49.alamar3"]);
+
+ } else if (map[HAS_EYE]) {
+ close();
+ map.redrawGame();
+ send("GameView", DrawMonsterMessage(7));
+ send("GameView", DrawMonsterMessage(6));
+
+ clearSurface();
+ writeString(0, 0, STRING["maps.map49.alamar1"]);
+ writeString(STRING["maps.map49.alamar4"]);
+
+ for (int i = 0; i < 6; ++i)
+ Sound::sound(SOUND_2);
+
+ } else {
+ clearSurface();
+ writeString(0, 0, STRING["maps.map49.alamar1"]);
+ writeString(STRING["maps.map49.alamar2"]);
+ }
+}
+
+bool Alamar::msgKeypress(const KeypressMessage &msg) {
+ MM1::Maps::Map49 &map = *static_cast<MM1::Maps::Map49 *>(g_maps->_currentMap);
+
+ close();
+ g_maps->_mapPos.x = 8;
+ map.redrawGame();
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/alamar.h b/engines/mm/mm1/views/maps/alamar.h
new file mode 100644
index 00000000000..762a4804ec1
--- /dev/null
+++ b/engines/mm/mm1/views/maps/alamar.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_ALAMAR_H
+#define MM1_VIEWS_MAPS_ALAMAR_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Alamar : public TextView {
+private:
+ bool _succeeded = false;
+public:
+ Alamar();
+ virtual ~Alamar() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/maps/orango.cpp b/engines/mm/mm1/views/maps/orango.cpp
index c2883b9b9c3..a8243849b57 100644
--- a/engines/mm/mm1/views/maps/orango.cpp
+++ b/engines/mm/mm1/views/maps/orango.cpp
@@ -53,7 +53,7 @@ void Orango::answerEntered() {
if (_answer == properAnswer) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._flags[13] |= CHARFLAG13_40;
+ c._flags[13] |= CHARFLAG13_ALAMAR;
}
g_maps->_mapPos = Common::Point(8, 5);
diff --git a/engines/mm/mm1/views/maps/prisoners.cpp b/engines/mm/mm1/views/maps/prisoners.cpp
index a88cfa5e02c..ac4dd7a844d 100644
--- a/engines/mm/mm1/views/maps/prisoners.cpp
+++ b/engines/mm/mm1/views/maps/prisoners.cpp
@@ -55,6 +55,7 @@ bool Prisoner::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_1:
line = STRING["maps.prisoners.flees"];
align = _freeAlignment;
+ flee();
break;
case Common::KEYCODE_2:
@@ -115,6 +116,17 @@ MutatedPrisoner::MutatedPrisoner() :
CHARFLAG1_2, GOOD, EVIL) {
}
+MaidenPrisoner::MaidenPrisoner() :
+ Prisoner("MaidenPrisoner", STRING["maps.prisoners.maiden"],
+ CHARFLAG1_8, GOOD, EVIL) {
+}
+
+void MaidenPrisoner::flee() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ map._walls[48] &= 0x7f;
+ g_maps->clearSpecial();
+}
+
} // namespace Maps
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/mm1/views/maps/prisoners.h b/engines/mm/mm1/views/maps/prisoners.h
index d282c883733..4a0d1a1f5a3 100644
--- a/engines/mm/mm1/views/maps/prisoners.h
+++ b/engines/mm/mm1/views/maps/prisoners.h
@@ -36,6 +36,8 @@ private:
byte _flag;
Alignment _freeAlignment;
Alignment _leaveAlignment;
+protected:
+ virtual void flee() {}
public:
Prisoner(const Common::String &name, const Common::String &line1,
byte flag, Alignment freeAlignment, Alignment leaveAlignment);
@@ -78,6 +80,15 @@ public:
}
};
+class MaidenPrisoner : public Prisoner {
+protected:
+ void flee() override;
+public:
+ MaidenPrisoner();
+ virtual ~MaidenPrisoner() {
+ }
+};
+
} // namespace Maps
} // namespace Views
} // namespace MM1
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 7c37f1246f0..b371f53a6a3 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -51,6 +51,7 @@ MODULE_OBJS := \
mm1/views/locations/temple.o \
mm1/views/locations/training.o \
mm1/views/maps/access_code.o \
+ mm1/views/maps/alamar.o \
mm1/views/maps/alien.o \
mm1/views/maps/answer_entry.o \
mm1/views/maps/arrested.o \
Commit: 731449d3bea92580cbaa4f8e4e58084b6e7ab6f8
https://github.com/scummvm/scummvm/commit/731449d3bea92580cbaa4f8e4e58084b6e7ab6f8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:29+01:00
Commit Message:
MM: MM1: Added map 50
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map50.cpp
engines/mm/mm1/maps/map50.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index c99ab62b7e0..fea25ac541f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1487,3 +1487,15 @@ maps:
trap: "SINGE! ACID TRAP."
explosion: "BOOM! A FIERY EXPLOSION."
throne_room: "THRONE ROOM"
+
+ map50:
+ message7: "ETCHED IN GOLD, MESSAGE 7 READS:\nTHESE-AND-THAT-MUST-CAN-DIFFERENT-\nSHALL-HAVE-FROM-A-JVC"
+ sign1: "CLUB DEAD...\nTHE ANTIDOTE TO HUMANIZATION!"
+ sign2: "TEMPLE OF THE OLD ORDER"
+ sign3: "GLASS ROOM"
+ sign4: "RUBY ROOM"
+ sign5: "TWINKLE ROOM"
+ sign6: "RAINBOW ROOM"
+ passage: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
+ painted: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+ grate: "THE CRYSTAL GRATE REPELS YOU!"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 81c0bcff246..17bebc915ba 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -39,6 +39,7 @@ enum ItemId {
RUBY_WHISTLE_ID = 232,
KINGS_PASS_ID = 233,
MERCHANTS_PASS_ID = 234,
+ CRYSTAL_KEY_ID = 235,
CORAL_KEY_ID = 236,
BRONZE_KEY_ID = 237,
SILVER_KEY_ID = 238,
diff --git a/engines/mm/mm1/maps/map50.cpp b/engines/mm/mm1/maps/map50.cpp
index 33a2e106d81..d6adfb4a683 100644
--- a/engines/mm/mm1/maps/map50.cpp
+++ b/engines/mm/mm1/maps/map50.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map50::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 24; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[75 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,132 @@ void Map50::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map50::special00() {
+ send(SoundMessage(STRING["maps.map50.message7"]));
+}
+
+void Map50::special01() {
+ send(SoundMessage(
+ STRING["maps.map50.passage"],
+ []() {
+ g_maps->_mapPos = Common::Point(10, 5);
+ g_maps->changeMap(0x11b, 2);
+ }
+ ));
+}
+
+void Map50::special02() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0x701, 3);
+ }
+ ));
+}
+
+void Map50::special03() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0xe00, 3);
+ }
+ ));
+}
+
+void Map50::special04() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0x201, 3);
+ }
+ ));
+}
+
+void Map50::special05() {
+ encounter(&_data[427], &_data[440]);
+}
+
+void Map50::special06() {
+ encounter(&_data[453], &_data[464]);
+}
+
+void Map50::special07() {
+ encounter(&_data[475], &_data[486]);
+}
+
+void Map50::special08() {
+ encounter(&_data[497], &_data[500]);
+}
+
+void Map50::special09() {
+ encounter(&_data[503], &_data[516]);
+}
+
+void Map50::special10() {
+ encounter(&_data[529], &_data[542]);
+}
+
+void Map50::special11() {
+ encounter(&_data[555], &_data[569]);
+}
+
+void Map50::special12() {
+ encounter(&_data[583], &_data[597]);
+}
+
+void Map50::special13() {
+ encounter(&_data[611], &_data[626]);
+}
+
+void Map50::special14() {
+ encounter(&_data[641], &_data[647]);
+}
+
+void Map50::special15() {
+ encounter(&_data[653], &_data[664]);
+}
+
+void Map50::special16() {
+ send(SoundMessage(STRING["maps.map50.sign1"]));
+}
+
+void Map50::special17() {
+ send(SoundMessage(STRING["maps.map50.sign2"]));
+}
+
+void Map50::special18() {
+ send(SoundMessage(STRING["maps.map50.sign3"]));
+}
+
+void Map50::special19() {
+ send(SoundMessage(STRING["maps.map50.sign4"]));
+}
+
+void Map50::special20() {
+ send(SoundMessage(STRING["maps.map50.sign5"]));
+}
+
+void Map50::special21() {
+ send(SoundMessage(STRING["maps.map50.sign6"]));
+}
+
+void Map50::special22() {
+ send(SoundMessage(STRING["maps.map50.sign6"]));
+}
+
+void Map50::special23() {
+ if (!(g_globals->_party.hasItem(CRYSTAL_KEY_ID))) {
+ g_maps->_mapPos.y--;
+ updateGame();
+
+ send(SoundMessage(STRING["maps.map50.grate"]));
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map50.h b/engines/mm/mm1/maps/map50.h
index 72c7bf7ef2c..433a49fd7b8 100644
--- a/engines/mm/mm1/maps/map50.h
+++ b/engines/mm/mm1/maps/map50.h
@@ -32,9 +32,55 @@ class Map50 : public Map {
typedef void (Map50:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special15();
+ void special16();
+ void special17();
+ void special18();
+ void special19();
+ void special20();
+ void special21();
+ void special22();
+ void special23();
- const SpecialFn SPECIAL_FN[1] = {
- &Map50::special00
+ const SpecialFn SPECIAL_FN[24] = {
+ &Map50::special00,
+ &Map50::special01,
+ &Map50::special02,
+ &Map50::special03,
+ &Map50::special04,
+ &Map50::special05,
+ &Map50::special06,
+ &Map50::special07,
+ &Map50::special08,
+ &Map50::special09,
+ &Map50::special10,
+ &Map50::special11,
+ &Map50::special12,
+ &Map50::special13,
+ &Map50::special14,
+ &Map50::special15,
+ &Map50::special16,
+ &Map50::special17,
+ &Map50::special18,
+ &Map50::special19,
+ &Map50::special20,
+ &Map50::special21,
+ &Map50::special22,
+ &Map50::special23
};
public:
Map50() : Map(50, "pp1", 0xF01) {}
Commit: 59ca90fe4cf78e697ab059d186f1585eb57489e1
https://github.com/scummvm/scummvm/commit/59ca90fe4cf78e697ab059d186f1585eb57489e1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:29+01:00
Commit Message:
MM: MM1: Added map 51
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map51.cpp
engines/mm/mm1/maps/map51.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index fea25ac541f..2a56dd28e05 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1499,3 +1499,7 @@ maps:
passage: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
painted: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
grate: "THE CRYSTAL GRATE REPELS YOU!"
+
+ map51:
+ painted: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+ substance: 'WITHOUT EXPERIMENTAL SUBSTANCE\nTHERE IS NO HOPE...POOF!"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 17bebc915ba..137d5f58a34 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -55,6 +55,8 @@ enum ItemId {
W_QUEEN_IDOL_ID = 249,
PIRATES_MAP_A_ID = 250,
PIRATES_MAP_B_ID = 251,
+ THUNDRANIUM_ID = 252,
+ KEY_CARD_ID = 253,
EYE_OF_GOROS_ID = 254,
USELESS_ITEM_ID = 255
};
diff --git a/engines/mm/mm1/maps/map51.cpp b/engines/mm/mm1/maps/map51.cpp
index 40bd7c76704..6df15f9265b 100644
--- a/engines/mm/mm1/maps/map51.cpp
+++ b/engines/mm/mm1/maps/map51.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map51::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 20; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[71 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,94 @@ void Map51::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map51::special00() {
+ send(SoundMessage(STRING["maps.map51.painted"]));
+}
+
+void Map51::special01() {
+ if (!g_globals->_party.hasItem(THUNDRANIUM_ID)) {
+ g_maps->_mapPos = Common::Point(
+ getRandomNumber(14), getRandomNumber(14));
+ updateGame();
+ send(SoundMessage(STRING["maps.map51.substance"]));
+ }
+}
+
+void Map51::special02() {
+ send(SoundMessage(
+ STRING["maps.stairs_down"],
+ []() {
+ g_maps->changeMap(0xe00, 3);
+ }
+ ));
+}
+
+void Map51::special03() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0xf01, 3);
+ }
+ ));
+}
+
+void Map51::special05() {
+ encounter(&_data[201], &_data[208]);
+}
+
+void Map51::special06() {
+ encounter(&_data[215], &_data[230]);
+}
+
+void Map51::special07() {
+ encounter(&_data[245], &_data[260]);
+}
+
+void Map51::special08() {
+ encounter(&_data[275], &_data[290]);
+}
+
+void Map51::special09() {
+ encounter(&_data[305], &_data[320]);
+}
+
+void Map51::special10() {
+ encounter(&_data[335], &_data[350]);
+}
+
+void Map51::special11() {
+ encounter(&_data[365], &_data[380]);
+}
+
+void Map51::special12() {
+ encounter(&_data[395], &_data[410]);
+}
+
+void Map51::special13() {
+ encounter(&_data[425], &_data[440]);
+}
+
+void Map51::special14() {
+ encounter(&_data[455], &_data[470]);
+}
+
+void Map51::special17() {
+ encounter(&_data[000], &_data[000]);
+}
+
+void Map51::special18() {
+ // No implementation
+}
+
+void Map51::special19() {
+ Sound::sound(SOUND_2);
+ none160();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map51.h b/engines/mm/mm1/maps/map51.h
index b40a9dcb40a..262c7f4f952 100644
--- a/engines/mm/mm1/maps/map51.h
+++ b/engines/mm/mm1/maps/map51.h
@@ -32,9 +32,44 @@ class Map51 : public Map {
typedef void (Map51:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
+ void special17();
+ void special18();
+ void special19();
- const SpecialFn SPECIAL_FN[1] = {
- &Map51::special00
+ const SpecialFn SPECIAL_FN[20] = {
+ &Map51::special00,
+ &Map51::special01,
+ &Map51::special02,
+ &Map51::special03,
+ &Map51::special01,
+ &Map51::special05,
+ &Map51::special06,
+ &Map51::special07,
+ &Map51::special08,
+ &Map51::special09,
+ &Map51::special10,
+ &Map51::special11,
+ &Map51::special12,
+ &Map51::special13,
+ &Map51::special14,
+ &Map51::special01,
+ &Map51::special01,
+ &Map51::special17,
+ &Map51::special18,
+ &Map51::special19
};
public:
Map51() : Map(51, "pp2", 0x701) {}
Commit: e8ebbe572de707ecb6cd7ffc5d8e3df8283ab27b
https://github.com/scummvm/scummvm/commit/e8ebbe572de707ecb6cd7ffc5d8e3df8283ab27b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:29+01:00
Commit Message:
MM: MM1: Added map 52
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map38.cpp
engines/mm/mm1/maps/map39.cpp
engines/mm/mm1/maps/map41.cpp
engines/mm/mm1/maps/map45.cpp
engines/mm/mm1/maps/map46.cpp
engines/mm/mm1/maps/map50.cpp
engines/mm/mm1/maps/map52.cpp
engines/mm/mm1/maps/map52.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 2a56dd28e05..e2933483e12 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -818,6 +818,7 @@ maps:
sign: "A SIGN ABOVE THE DOOR READS:\n"
stairs_up: "STAIRS GOING UP! TAKE THEM (Y/N)?"
stairs_down: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
+ wall_painted: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
desert:
its_hot: "IT'S HOT... "
@@ -1354,7 +1355,6 @@ maps:
archway: "A GEM ENCRUSTED ARCHWAY READS:\nLAIR OF THE OMNIPOTENT WIZARD OKRIM"
opening: "AN OPENING ABOVE LEADS OUTSIDE,\nCLIMB OUT (Y/N)?"
spins: "THE FLOOR SPINS!"
- wall: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
map38:
message4: "ETCHED IN GOLD, MESSAGE 4 READS:'\nOF-BE-HAS-TRUE-KNOWLEDGE-PLANE-A-LEVEL-'\nTO-REALITY-IT"
@@ -1363,7 +1363,6 @@ maps:
face2: "INSET IN THE WALL, A STONE FACE\nSPEAKS: ""I WOULD PAY HIGHLY FOR A GREEN\nHANDLED, PEARL ENCRUSTED ABELNUSKI."""
face3: "INSET IN THE WALL, A STONE FACE\nSPEAKS: ""I SEE ALL, HEAR ALL,\nKNOW NOTHING..."""
face4: "INSET IN THE WALL, A STONE FACE\nPROCLAIMS: ""OKRIM IS WATCHING.\nHE STUDIES YOUR WEAKNESSES!"""
- wall: THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
ringing: "A STRANGE RINGING SOUND STARTLES\nTHE PARTY. YOU ARE TELEPORTED!"
map39:
@@ -1373,7 +1372,6 @@ maps:
door_repels: "A SILVER DOOR REPELS YOU!"
door_glows: "A SILVER DOOR, YOUR SILVER KEY GLOWS!"
stairs_up: "STAIRS TO SURFACE, TAKE THEM (Y/N)?"
- room: "THE ROOM IS PAINTED IN A BLACK AND\nWHITE CHECKERED PATTERN!"
map40:
message2: "ETCHED IN GOLD, MESSAGE 2 READS:\nONE,-RIDDLES-VALUE-YOU-YOU-5-CARD-MUST-\nCLAIMED.-DREAMS,-..."
@@ -1397,7 +1395,6 @@ maps:
sign4: "THE UGLIES CLUB - MEMBERS ONLY!"
sign5: "SPECIMEN TANK - KEEP CLOSED"
stairs_up: "SPIRALLING STAIRS GO UP,TAKE THEM (Y/N)?"
- room: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
tapestry1: "A TAPESTRY ON THE WALL DEPICTS A GRAY\nMINOTAUR STOMPING ON A GROUP OF KNIGHTS."
tapestry2: "A TAPESTRY ON THE WALL DEPICTS\nA KINGDOM RULED BY MINOTAURS"
@@ -1446,10 +1443,8 @@ maps:
walls: "THE WALLS GLOW OMINOUSLY"
message: "ETCHED IN STONE:\n""28 DAYS OUT. NO FOOD, LOW ON SUPPLIES.\nWE FEAR THE WORST YET WE CONTINUE-CORAK"
passage: "A CAVERNOUS PASSAGE, TAKE IT (Y/N)?"
- wall: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
map46:
- painted: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
shakes: "THE GROUND SHAKES!"
clerics: "CLERICS OF THE SOUTH JUST BELOW-CORAK"
@@ -1497,9 +1492,10 @@ maps:
sign5: "TWINKLE ROOM"
sign6: "RAINBOW ROOM"
passage: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
- painted: "THE ROOM IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
grate: "THE CRYSTAL GRATE REPELS YOU!"
map51:
- painted: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
substance: 'WITHOUT EXPERIMENTAL SUBSTANCE\nTHERE IS NO HOPE...POOF!"
+
+ map52:
+ summoned: "YOU HAVE BEEN SUMMONED...POOF!"
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index a4875501e3d..784fe23069f 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -152,7 +152,7 @@ void Map37::special14() {
}
void Map37::special15() {
- send(SoundMessage(STRING["maps.map37.wall"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
if (!g_globals->_party.hasItem(B_QUEEN_IDOL_ID)) {
g_globals->_treasure[5] = B_QUEEN_IDOL_ID;
diff --git a/engines/mm/mm1/maps/map38.cpp b/engines/mm/mm1/maps/map38.cpp
index 572b30cb1c5..dc66b2b0599 100644
--- a/engines/mm/mm1/maps/map38.cpp
+++ b/engines/mm/mm1/maps/map38.cpp
@@ -55,7 +55,7 @@ void Map38::special00() {
}
void Map38::special01() {
- send(SoundMessage(STRING["maps.map38.wall"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
}
void Map38::special02() {
diff --git a/engines/mm/mm1/maps/map39.cpp b/engines/mm/mm1/maps/map39.cpp
index 809380c2cb7..4b5a56856a9 100644
--- a/engines/mm/mm1/maps/map39.cpp
+++ b/engines/mm/mm1/maps/map39.cpp
@@ -132,7 +132,7 @@ void Map39::special14() {
}
void Map39::special18() {
- send(SoundMessage(STRING["maps.map39.room"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map41.cpp b/engines/mm/mm1/maps/map41.cpp
index 6a17dfae587..7269e929e72 100644
--- a/engines/mm/mm1/maps/map41.cpp
+++ b/engines/mm/mm1/maps/map41.cpp
@@ -139,7 +139,7 @@ void Map41::special20() {
}
void Map41::special21() {
- send(SoundMessage(STRING["maps.map41.room"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
}
void Map41::special22() {
diff --git a/engines/mm/mm1/maps/map45.cpp b/engines/mm/mm1/maps/map45.cpp
index 5185867736f..1ea735b76a4 100644
--- a/engines/mm/mm1/maps/map45.cpp
+++ b/engines/mm/mm1/maps/map45.cpp
@@ -146,7 +146,7 @@ void Map45::special20() {
}
void Map45::special21() {
- send(SoundMessage(STRING["maps.map45.wall"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
}
void Map45::showSign(const Common::String &line) {
diff --git a/engines/mm/mm1/maps/map46.cpp b/engines/mm/mm1/maps/map46.cpp
index 13532a373d4..72ea64573b9 100644
--- a/engines/mm/mm1/maps/map46.cpp
+++ b/engines/mm/mm1/maps/map46.cpp
@@ -50,7 +50,7 @@ void Map46::special() {
}
void Map46::special00() {
- send(SoundMessage(STRING["maps.map46.painted"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
}
void Map46::special01() {
@@ -59,7 +59,7 @@ void Map46::special01() {
void Map46::special02() {
send(SoundMessage(
- STRING["maps.map46.painted"],
+ STRING["maps.stairs_down"],
[]() {
g_maps->changeMap(0x705, 3);
}
@@ -68,7 +68,7 @@ void Map46::special02() {
void Map46::special03() {
send(SoundMessage(
- STRING["maps.map46.painted"],
+ STRING["maps.stairs_up"],
[]() {
g_maps->changeMap(0xf05, 3);
}
diff --git a/engines/mm/mm1/maps/map50.cpp b/engines/mm/mm1/maps/map50.cpp
index d6adfb4a683..bc0de523b31 100644
--- a/engines/mm/mm1/maps/map50.cpp
+++ b/engines/mm/mm1/maps/map50.cpp
@@ -159,7 +159,7 @@ void Map50::special21() {
}
void Map50::special22() {
- send(SoundMessage(STRING["maps.map50.sign6"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
}
void Map50::special23() {
diff --git a/engines/mm/mm1/maps/map52.cpp b/engines/mm/mm1/maps/map52.cpp
index b413d30ef5e..99edcc85c10 100644
--- a/engines/mm/mm1/maps/map52.cpp
+++ b/engines/mm/mm1/maps/map52.cpp
@@ -31,12 +31,11 @@ namespace Maps {
void Map52::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 7; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[58 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +43,45 @@ void Map52::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map52::special00() {
+ send(SoundMessage(STRING["maps.wall_painted"]));
+}
+
+void Map52::special01() {
+ _walls[0x18] |= 0x80;
+ g_maps->_mapPos = Common::Point(8, 1);
+ updateGame();
+
+ send(SoundMessage(STRING["maps.map52.summoned"]));
+}
+
+void Map52::special03() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0x701, 3);
+ }
+ ));
+}
+
+void Map52::special04() {
+ send(SoundMessage(
+ STRING["maps.stairs_up"],
+ []() {
+ g_maps->changeMap(0xf01, 3);
+ }
+ ));
+}
+
+void Map52::special06() {
+ g_maps->_mapPos = Common::Point(15, 7);
+ updateGame();
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map52.h b/engines/mm/mm1/maps/map52.h
index f4c942dd7d7..9705f599cae 100644
--- a/engines/mm/mm1/maps/map52.h
+++ b/engines/mm/mm1/maps/map52.h
@@ -32,9 +32,19 @@ class Map52 : public Map {
typedef void (Map52:: *SpecialFn)();
private:
void special00();
-
- const SpecialFn SPECIAL_FN[1] = {
- &Map52::special00
+ void special01();
+ void special03();
+ void special04();
+ void special06();
+
+ const SpecialFn SPECIAL_FN[7] = {
+ &Map52::special00,
+ &Map52::special01,
+ &Map52::special01,
+ &Map52::special03,
+ &Map52::special04,
+ &Map52::special01,
+ &Map52::special06
};
public:
Map52() : Map(52, "pp3", 0xE00) {}
Commit: 5a4e052da51ceef860824f8a078b100aa4ba0ad3
https://github.com/scummvm/scummvm/commit/5a4e052da51ceef860824f8a078b100aa4ba0ad3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:30+01:00
Commit Message:
MM: MM1: Added map 53
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map53.cpp
engines/mm/mm1/maps/map53.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index e2933483e12..7f4b17a7a8c 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1499,3 +1499,7 @@ maps:
map52:
summoned: "YOU HAVE BEEN SUMMONED...POOF!"
+
+ map53:
+ sign: "DANGER! DUNGEON UNDER CONSTRUCTION."
+ ladder: "A LADDER GOING UP, CLIMB IT (Y/N)?"
diff --git a/engines/mm/mm1/maps/map53.cpp b/engines/mm/mm1/maps/map53.cpp
index c4436a5be20..621bcc86b2c 100644
--- a/engines/mm/mm1/maps/map53.cpp
+++ b/engines/mm/mm1/maps/map53.cpp
@@ -29,14 +29,15 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 379
+
void Map53::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 15; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[66 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +45,75 @@ void Map53::special() {
return;
}
}
-/*
+
// All other cells on the map are encounters
g_maps->clearSpecial();
g_globals->_encounters.execute();
- */
}
void Map53::special00() {
+ send(SoundMessage(STRING["maps.wall_painted"]));
+ if (!_data[VAL1]) {
+ g_globals->_treasure[5] = W_QUEEN_IDOL_ID;
+ _data[VAL1]++;
+ }
+}
+
+void Map53::special01() {
+ send(SoundMessage(STRING["maps.map53.sign"]));
+}
+
+void Map53::special03() {
+ send(SoundMessage(
+ STRING["maps.map53.ladder_up"],
+ []() {
+ g_maps->changeMap(0xf01, 3);
+ }
+ ));
+}
+
+void Map53::special04() {
+ g_globals->_encounters.execute();
+}
+
+void Map53::special05() {
+ encounter(&_data[182], &_data[190]);
+}
+
+void Map53::special06() {
+ encounter(&_data[198], &_data[205]);
+}
+
+void Map53::special07() {
+ encounter(&_data[212], &_data[220]);
+}
+
+void Map53::special08() {
+ encounter(&_data[228], &_data[234]);
+}
+
+void Map53::special09() {
+ encounter(&_data[240], &_data[252]);
+}
+
+void Map53::special10() {
+ encounter(&_data[264], &_data[274]);
+}
+
+void Map53::special11() {
+ encounter(&_data[284], &_data[288]);
+}
+
+void Map53::special12() {
+ encounter(&_data[292], &_data[296]);
+}
+
+void Map53::special13() {
+ encounter(&_data[300], &_data[304]);
+}
+
+void Map53::special14() {
+ encounter(&_data[308], &_data[312]);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map53.h b/engines/mm/mm1/maps/map53.h
index 518d50e525c..f0d7347c03a 100644
--- a/engines/mm/mm1/maps/map53.h
+++ b/engines/mm/mm1/maps/map53.h
@@ -32,9 +32,36 @@ class Map53 : public Map {
typedef void (Map53:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void special08();
+ void special09();
+ void special10();
+ void special11();
+ void special12();
+ void special13();
+ void special14();
- const SpecialFn SPECIAL_FN[1] = {
- &Map53::special00
+ const SpecialFn SPECIAL_FN[15] = {
+ &Map53::special00,
+ &Map53::special01,
+ &Map53::special01,
+ &Map53::special03,
+ &Map53::special04,
+ &Map53::special05,
+ &Map53::special06,
+ &Map53::special07,
+ &Map53::special08,
+ &Map53::special09,
+ &Map53::special10,
+ &Map53::special11,
+ &Map53::special12,
+ &Map53::special13,
+ &Map53::special14
};
public:
Map53() : Map(53, "pp4", 0x201) {}
Commit: e801eb10472c6a7d673dd1ca689ae5986b6b54b4
https://github.com/scummvm/scummvm/commit/e801eb10472c6a7d673dd1ca689ae5986b6b54b4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:30+01:00
Commit Message:
MM: MM1: Added map 54. The last damn map.. finally
Changed paths:
A engines/mm/mm1/views/maps/keeper.cpp
A engines/mm/mm1/views/maps/keeper.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/maps/map54.cpp
engines/mm/mm1/maps/map54.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 7f4b17a7a8c..20bc5a95587 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1503,3 +1503,16 @@ maps:
map53:
sign: "DANGER! DUNGEON UNDER CONSTRUCTION."
ladder: "A LADDER GOING UP, CLIMB IT (Y/N)?"
+
+ map54:
+ projector: "ASTRAL PROJECTOR # %c , ZAP!"
+ slot1: "THERE'S A SMALL SLOT IN THE DOOR.\n"
+ slot2: "NO ADMITTANCE!"
+ slot3: "KEY CARD IS REJECTED!"
+ slot4: "KEY CARD IS ACCEPTED!"
+ glow: "THE METALLIC ROOM IS DIMLY LIT BY\nA PULSATING WHITE GLOW!"
+ keeper1: "A METALLIC PANEL SLIDES OPEN, REVEALING\nA MYSTERIOUS MAN IN A WHITE COAT...\n(PRESS SPACE TO COMMUNICATE)"
+ keeper2: ":::INNER SANCTUM:::"
+ keeper3: "IN A SERENE VOICE, THE DATA KEEPER SAYS,\n""WELCOME TO YOUR INNER SANCTUM\nVARNLINGS! I AM VERY PLEASED THAT YOU'VE\nMADE IT THIS FAR. YOU ARE TO BE\nCOMMENDED. I'VE BEEN MONITORING YOUR\nPROGRESS."" TURNING TO THE STRANGE\nMECHANICAL DEVICE, HE INSERTS A FLAT\nOBJECT INTO A SLOT. YOUR PARTY'S CURRENT\nPERFORMANCE TOTAL=%u"
+ keeper4: """YOU ARE NOT YET WORTHY FOR TRANSFER. RETURN AFTER DEFEATING THE IMPOSTER."""
+ keeper5: "EXCELLENT RATING! THIS IS A RARE OCCASION, FOR ONLY A PRIVILEGED FEW ARE GIVEN THE OPPORTUNITY FOR TRANSFER TO\nANOTHER V.A.R.N. (VEHICULAR ASTROPOD\nRESEARCH NACELLE). RETURN NOW TO THE\nINN OF SORPIGAL FOR REST AND CELEBRATION\nTHEN CONTINUE ON TO YOUR NEW ASSIGNMENT AT THE GATES TO ANOTHER WORLD..."" (+50000 EXP FOR YOUR ACCOMPLISHMENT!)\n----------------------------------------\nPLEASE SEND YOUR PERFORMANCE TOTAL TO\nNEW WORLD COMPUTING, INC.\n P. O. BOX 2068 VAN NUYS, CA 91404"
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 58b990bf593..90f9e6f6060 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -40,6 +40,13 @@ void Resistances::synchronize(Common::Serializer &s) {
_arr[i].synchronize(s);
}
+size_t Resistances::getPerformanceTotal() const {
+ size_t total = 0;
+ for (int i = 0; i < 8; ++i)
+ total += _arr[i].getPerformanceTotal();
+ return total;
+}
+
void Inventory::clear() {
_items.clear();
_items.resize(INVENTORY_COUNT);
@@ -137,6 +144,13 @@ void Inventory::removeCharge(Entry *e) {
}
}
+size_t Inventory::getPerformanceTotal() const {
+ size_t total = 0;
+ for (uint i = 0; i < size(); ++i)
+ total += (size_t)(*this)[i]._id + (size_t)(*this)[i]._charges;
+
+ return total;
+}
/*------------------------------------------------------------------------*/
@@ -580,5 +594,51 @@ bool Character::hasItem(byte itemId) const {
_equipped.indexOf(itemId) != -1;
}
+#define PERF16(x) ((x & 0xff) + ((x >> 8) & 0xff))
+#define PERF32(x) ((x & 0xff) + ((x >> 8) & 0xff) + \
+ ((x >> 16) & 0xff) + ((x >> 24) & 0xff))
+
+size_t Character::getPerformanceTotal() const {
+ size_t totalFlags = 0;
+ for (int i = 0; i < 14; ++i)
+ totalFlags += _flags[i];
+
+ return (int)_sex
+ + _alignmentInitial
+ + _alignment
+ + _race
+ + _class
+ + _intelligence.getPerformanceTotal()
+ + _might.getPerformanceTotal()
+ + _personality.getPerformanceTotal()
+ + _endurance.getPerformanceTotal()
+ + _speed.getPerformanceTotal()
+ + _accuracy.getPerformanceTotal()
+ + _luck.getPerformanceTotal()
+ + _level.getPerformanceTotal()
+ + _age.getPerformanceTotal()
+ + PERF32(_exp)
+ + _sp.getPerformanceTotal()
+ + _spellLevel.getPerformanceTotal()
+ + PERF16(_gems)
+ + PERF16(_hpBase)
+ + PERF16(_hp)
+ + PERF16(_hpMax)
+ + PERF32(_gold)
+ + _ac
+ + _food
+ + _condition
+ + _equipped.getPerformanceTotal()
+ + _backpack.getPerformanceTotal()
+ + _resistances.getPerformanceTotal()
+ + _physicalAttr.getPerformanceTotal()
+ + _missileAttr.getPerformanceTotal()
+ + _v6c
+ + _quest
+ + _v6e
+ + _alignmentCtr
+ + totalFlags;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 1dde59a674b..6a861ab2b93 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -307,6 +307,8 @@ public:
bool hasTwoHanded() const { return hasCategory(isTwoHanded); }
bool hasArmor() const { return hasCategory(isArmor); }
bool hasShield() const { return hasCategory(isShield); }
+
+ size_t getPerformanceTotal() const;
};
/**
@@ -338,6 +340,10 @@ struct AttributePair {
s.syncAsByte(_base);
s.syncAsByte(_current);
}
+
+ size_t getPerformanceTotal() const {
+ return (size_t)_base + (size_t)_current;
+ }
};
struct AttributePair16 {
@@ -353,6 +359,11 @@ struct AttributePair16 {
s.syncAsUint16LE(_base);
s.syncAsUint16LE(_current);
}
+
+ size_t getPerformanceTotal() const {
+ return (_base & 0xff) + (_base >> 8) +
+ (_current & 0xff) + (_current >> 8);
+ }
};
struct ResistanceFields {
@@ -376,6 +387,8 @@ union Resistances {
* Handles save/loading resistences
*/
void synchronize(Common::Serializer &s);
+
+ size_t getPerformanceTotal() const;
};
struct PrimaryAttributes {
@@ -429,6 +442,7 @@ struct Character : public PrimaryAttributes {
byte _v6e;
int _alignmentCtr;
byte _flags[14];
+ byte _lastField = 0;
// Non persistent fields
byte _numDrinks = 0;
@@ -510,6 +524,13 @@ struct Character : public PrimaryAttributes {
* Returns true if the character has a given item
*/
bool hasItem(byte itemId) const;
+
+ /**
+ * Gets the numeric value of every property a character
+ * has and totals it up to give a stupid 'performance'
+ * value for the party at the end of the game
+ */
+ size_t getPerformanceTotal() const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index bd5b86fa03c..8e5cac33ea8 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -29,14 +29,18 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define PERF_TOTAL 1293
+#define VAL2 1296
+
+static byte FLAGS[5] = { 1, 2, 4, 8, 0x10 };
+
void Map54::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 8; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[75 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
@@ -44,14 +48,115 @@ void Map54::special() {
return;
}
}
-/*
- // All other cells on the map are encounters
- g_maps->clearSpecial();
- g_globals->_encounters.execute();
- */
+
+ checkPartyDead();
}
void Map54::special00() {
+ if (!g_globals->_party.hasItem(KEY_CARD_ID)) {
+ g_maps->_mapPos.y++;
+ updateGame();
+
+ send(SoundMessage(
+ 0, 1, STRING["maps.map54.slot1"],
+ 0, 1, STRING["maps.map54.slot2"]
+ ));
+ return;
+ }
+
+ // Check for flag
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if ((c._flags[13] & (CHARFLAG13_1 or CHARFLAG13_2 or CHARFLAG13_4 or CHARFLAG13_8 or CHARFLAG13_10)) !=
+ (CHARFLAG13_1 or CHARFLAG13_2 or CHARFLAG13_4 or CHARFLAG13_8 or CHARFLAG13_10)) {
+ g_maps->_mapPos.y++;
+ updateGame();
+
+ send(SoundMessage(
+ 0, 1, STRING["maps.map54.slot1"],
+ 0, 1, STRING["maps.map54.slot3"]
+ ));
+ return;
+ }
+ }
+
+ send(SoundMessage(
+ 0, 1, STRING["maps.map54.slot1"],
+ 0, 2, STRING["maps.map54.slot4"]
+ ));
+}
+
+void Map54::special01() {
+ projector(0);
+}
+
+void Map54::special02() {
+ projector(1);
+}
+
+void Map54::special03() {
+ projector(2);
+}
+
+void Map54::special04() {
+ projector(3);
+}
+
+void Map54::special05() {
+ projector(4);
+}
+
+void Map54::special06() {
+ send(SoundMessage(STRING["maps.map54.glow"]));
+}
+
+void Map54::special07() {
+ send("GameView", DrawMonsterMessage(5));
+ g_events->addView("Keeper");
+}
+
+void Map54::projector(int index) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ g_globals->_party[i]._flags[13] |= FLAGS[index];
+ }
+
+ changeMap();
+
+ Common::String line = Common::String::format(
+ STRING["maps.map54.projector"].c_str(),
+ '1' + index);
+ send(SoundMessage(line));
+}
+
+bool Map54::isWorthy(uint32 &perfTotal) {
+ perfTotal = 0;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (c._flags[13] & CHARFLAG13_80) {
+ _data[VAL2]++;
+ } else if (c._flags[13] & CHARFLAG13_ALAMAR) {
+ c._exp += 500000;
+ c._flags[13] = 0xff;
+ _data[VAL2]++;
+ }
+
+ // Calculate performance totals for party
+ perfTotal += c.getPerformanceTotal();
+ if (c._flags[13] & CHARFLAG13_80)
+ perfTotal += 65536;
+ }
+
+ _data[PERF_TOTAL + 0] = perfTotal & 0xff;
+ _data[PERF_TOTAL + 1] = (perfTotal >> 8) & 0xff;
+ _data[PERF_TOTAL + 2] = (perfTotal >> 16) & 0xff;
+
+ return perfTotal >= 65536;
+}
+
+void Map54::changeMap() {
+ g_maps->_mapPos = Common::Point(8, 5);
+ g_maps->changeMap(0x604, 1);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map54.h b/engines/mm/mm1/maps/map54.h
index 12126ed668d..039bcf44ed0 100644
--- a/engines/mm/mm1/maps/map54.h
+++ b/engines/mm/mm1/maps/map54.h
@@ -32,9 +32,24 @@ class Map54 : public Map {
typedef void (Map54:: *SpecialFn)();
private:
void special00();
+ void special01();
+ void special02();
+ void special03();
+ void special04();
+ void special05();
+ void special06();
+ void special07();
+ void projector(int index);
- const SpecialFn SPECIAL_FN[1] = {
- &Map54::special00
+ const SpecialFn SPECIAL_FN[8] = {
+ &Map54::special00,
+ &Map54::special01,
+ &Map54::special02,
+ &Map54::special03,
+ &Map54::special04,
+ &Map54::special05,
+ &Map54::special06,
+ &Map54::special07
};
public:
Map54() : Map(54, "astral", 0xB1A) {}
@@ -43,6 +58,16 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Determines whether the party is worthy
+ */
+ bool isWorthy(uint32 &perfTotal);
+
+ /**
+ * Changes the map
+ */
+ void changeMap();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 02420b05519..56270de9617 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -52,6 +52,7 @@
#include "mm/mm1/views/maps/giant.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/inspectron.h"
+#include "mm/mm1/views/maps/keeper.h"
#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/lord_archer.h"
#include "mm/mm1/views/maps/lord_ironfist.h"
@@ -112,6 +113,7 @@ private:
Views::Maps::Giant _giant;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Inspectron _inspectron;
+ Views::Maps::Keeper _keeper;
Views::Maps::Lion _lion;
Views::Maps::LordArcher _lordArcher;
Views::Maps::LordIronfist _lordIronfist;
diff --git a/engines/mm/mm1/views/maps/keeper.cpp b/engines/mm/mm1/views/maps/keeper.cpp
new file mode 100644
index 00000000000..3998e5fdfb1
--- /dev/null
+++ b/engines/mm/mm1/views/maps/keeper.cpp
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/maps/keeper.h"
+#include "mm/mm1/maps/map54.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+Keeper::Keeper() : TextView("Keeper") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Keeper::msgFocus(const FocusMessage &msg) {
+ _pageNum = 0;
+ Sound::sound(SOUND_2);
+
+ return TextView::msgFocus(msg);
+}
+
+void Keeper::draw() {
+ MM1::Maps::Map54 &map = *static_cast<MM1::Maps::Map54 *>(g_maps->_currentMap);
+ uint32 perfTotal;
+ bool isWorthy;
+
+ switch (_pageNum) {
+ case 0:
+ _bounds = getLineBounds(20, 24);
+ clearSurface();
+ writeString(0, 1, STRING["maps.map54.keeper1"]);
+ break;
+
+ case 1:
+ _bounds = getLineBounds(0, 24);
+ isWorthy = map.isWorthy(perfTotal);
+
+ clearSurface();
+ writeString(10, 0, STRING["maps.map54.keeper2"]);
+ writeString(0, 2, Common::String::format(
+ STRING["maps.map54.keeper3"].c_str(), perfTotal));
+ _textPos.y++;
+ writeString(STRING[isWorthy ? "maps.map54.keeper5" :
+ "maps.map54.keeper4"]);
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool Keeper::msgKeypress(const KeypressMessage &msg) {
+ MM1::Maps::Map54 &map = *static_cast<MM1::Maps::Map54 *>(g_maps->_currentMap);
+
+ if (++_pageNum == 2) {
+ close();
+ map.changeMap();
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/keeper.h b/engines/mm/mm1/views/maps/keeper.h
new file mode 100644
index 00000000000..212051f648b
--- /dev/null
+++ b/engines/mm/mm1/views/maps/keeper.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_KEEPER_H
+#define MM1_VIEWS_MAPS_KEEPER_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Keeper : public TextView {
+private:
+ int _pageNum = 0;
+public:
+ Keeper();
+ virtual ~Keeper() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b371f53a6a3..dfa701072e5 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -63,6 +63,7 @@ MODULE_OBJS := \
mm1/views/maps/hacker.o \
mm1/views/maps/ice_princess.o \
mm1/views/maps/inspectron.o \
+ mm1/views/maps/keeper.o \
mm1/views/maps/lion.o \
mm1/views/maps/lord_archer.o \
mm1/views/maps/lord_ironfist.o \
Commit: e0b9e7064cd9c20c77f0fa6624a33478d54a4558
https://github.com/scummvm/scummvm/commit/e0b9e7064cd9c20c77f0fa6624a33478d54a4558
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:30+01:00
Commit Message:
MM: MM1: Change DrawMonsterMessage to DrawGraphicMessage
Although the graphics come from "monpix.dta", several
maps display figure images, and search shows an image
for a cloth sack. So I've changed the drawing message
to be a more generic DrawGraphic
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map54.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/maps/alamar.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index bed0c027b03..49e7462daea 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -236,7 +236,7 @@ public:
MESSAGE(Game);
MESSAGE(Info);
MESSAGE(Value);
- MESSAGE(DrawMonster);
+ MESSAGE(DrawGraphic);
#undef MESSAGE
};
@@ -267,7 +267,7 @@ protected:
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
- MESSAGE(DrawMonster);
+ MESSAGE(DrawGraphic);
#undef MESSAGE
public:
Events(bool enhancedMode);
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 6794b6bf5fc..203505ce796 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -97,7 +97,7 @@ void Map35::special04() {
void Map35::special05() {
updateFlags();
- send("GameView", DrawMonsterMessage(7));
+ send("GameView", DrawGraphicMessage(7));
g_events->addView("Inspectron");
}
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index 5e51e466448..2981d92c975 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -94,7 +94,7 @@ void Map36::special04() {
void Map36::special05() {
updateFlags();
- send("GameView", DrawMonsterMessage(7));
+ send("GameView", DrawGraphicMessage(7));
g_events->addView("Hacker");
}
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 6cd88fb8259..de4d2c69ba9 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -105,7 +105,7 @@ void Map43::special04() {
void Map43::special05() {
updateFlags();
- send("GameView", DrawMonsterMessage(7));
+ send("GameView", DrawGraphicMessage(7));
g_events->addView("LordIronfist");
}
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index e6212b68a5e..4fa2051f808 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -106,7 +106,7 @@ void Map49::special06() {
g_maps->changeMap(0x412, 3);
} else {
- send("GameView", DrawMonsterMessage(7));
+ send("GameView", DrawGraphicMessage(7));
g_events->addView("Alamar");
}
}
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index 8e5cac33ea8..cdd0600317b 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -111,7 +111,7 @@ void Map54::special06() {
}
void Map54::special07() {
- send("GameView", DrawMonsterMessage(5));
+ send("GameView", DrawGraphicMessage(5));
g_events->addView("Keeper");
}
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 61cad4d8b48..33e2fa9f90c 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -172,12 +172,12 @@ struct ValueMessage : public Message {
_value(value) {}
};
-struct DrawMonsterMessage : public Message {
- int _monsterNum;
+struct DrawGraphicMessage : public Message {
+ int _gfxNum;
- DrawMonsterMessage() : Message(), _monsterNum(0) {}
- explicit DrawMonsterMessage(int monsterNum) : Message(),
- _monsterNum(monsterNum) {}
+ DrawGraphicMessage() : Message(), _gfxNum(0) {}
+ explicit DrawGraphicMessage(int gfxNum) : Message(),
+ _gfxNum(gfxNum) {}
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 45549efcf39..81cef311828 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -123,7 +123,7 @@ void Encounter::draw() {
if (_mode != ALERT) {
// Display the monster
- msgDrawMonster(DrawMonsterMessage(enc._monsterImgNum));
+ msgDrawGraphic(DrawGraphicMessage(enc._monsterImgNum));
// Write the monster list
for (uint i = 0; i < enc._monsterList.size(); ++i) {
diff --git a/engines/mm/mm1/views/maps/alamar.cpp b/engines/mm/mm1/views/maps/alamar.cpp
index bc1df7b77dd..fdd3c363eed 100644
--- a/engines/mm/mm1/views/maps/alamar.cpp
+++ b/engines/mm/mm1/views/maps/alamar.cpp
@@ -66,8 +66,8 @@ void Alamar::draw() {
} else if (map[HAS_EYE]) {
close();
map.redrawGame();
- send("GameView", DrawMonsterMessage(7));
- send("GameView", DrawMonsterMessage(6));
+ send("GameView", DrawGraphicMessage(7));
+ send("GameView", DrawGraphicMessage(6));
clearSurface();
writeString(0, 0, STRING["maps.map49.alamar1"]);
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 21b73fc60c1..85d7982656d 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -139,9 +139,9 @@ void TextView::timeout() {
redraw();
}
-bool TextView::msgDrawMonster(const DrawMonsterMessage &msg) {
+bool TextView::msgDrawGraphic(const DrawGraphicMessage &msg) {
Graphics::ManagedSurface img =
- g_globals->_monsters.getMonsterImage(msg._monsterNum);
+ g_globals->_monsters.getMonsterImage(msg._gfxNum);
getSurface().blitFrom(img, Common::Point(64, 16));
return true;
}
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 27596cd7f40..4a7df7893eb 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -102,7 +102,7 @@ public:
TextView(const Common::String &name, UIElement *owner);
virtual ~TextView() {}
- bool msgDrawMonster(const DrawMonsterMessage &msg) override;
+ bool msgDrawGraphic(const DrawGraphicMessage &msg) override;
};
} // namespace Views
Commit: a9303b908e3aec768eb181563faa44bf99ef985a
https://github.com/scummvm/scummvm/commit/a9303b908e3aec768eb181563faa44bf99ef985a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:30+01:00
Commit Message:
MM: MM1: Beginnings of proper search view
Changed paths:
A engines/mm/mm1/data/treasure.cpp
A engines/mm/mm1/data/treasure.h
A engines/mm/mm1/views/search.cpp
A engines/mm/mm1/views/search.h
R engines/mm/mm1/game/search.cpp
R engines/mm/mm1/game/search.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/globals.h
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map42.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 20bc5a95587..a6bf254aa2e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -141,6 +141,18 @@
search: "SEARCH: "
you_found: "YOU FOUND..."
nothing: "NOTHING"
+ containers:
+ 0: " CLOTH SACK "
+ 1: "LEATHER SACK"
+ 2: " WOODEN BOX "
+ 3: "WOODEN CHEST"
+ 4: " IRON BOX "
+ 5: " IRON CHEST "
+ 6: " SILVER BOX "
+ 7: "SILVER CHEST"
+ 8: " GOLD BOX "
+ 9: " GOLD CHEST "
+ 10: " BLACK BOX "
statues:
stone: "ON THIS STONE STATUE OF "
plaque: "A PLAQUE READS..."
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 137d5f58a34..64bab7a7a5b 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -113,24 +113,6 @@ struct ItemsArray : public Common::Array<Item>, public TextParser {
Item *getItem(byte index) const;
};
-class Treasure {
-private:
- byte _data[TREASURE_COUNT];
-public:
- Treasure() {
- clear();
- }
-
- byte &operator[](uint i) {
- assert(i < TREASURE_COUNT);
- return _data[i];
- }
-
- void clear() {
- Common::fill(&_data[0], &_data[TREASURE_COUNT], 0);
- }
-};
-
inline bool isWeapon(byte id) {
return id >= 1 && id <= 60;
};
diff --git a/engines/mm/mm1/game/search.h b/engines/mm/mm1/data/treasure.cpp
similarity index 87%
rename from engines/mm/mm1/game/search.h
rename to engines/mm/mm1/data/treasure.cpp
index 6c0c92bae36..4703a840654 100644
--- a/engines/mm/mm1/game/search.h
+++ b/engines/mm/mm1/data/treasure.cpp
@@ -19,19 +19,10 @@
*
*/
-#ifndef MM1_GAME_SEARCH_H
-#define MM1_GAME_SEARCH_H
+#include "mm/mm1/data/treasure.h"
namespace MM {
namespace MM1 {
-namespace Game {
-struct Search {
- static void execute();
-};
-
-} // namespace Game
} // namespace MM1
} // namespace MM
-
-#endif
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
new file mode 100644
index 00000000000..f4f5e4cd71f
--- /dev/null
+++ b/engines/mm/mm1/data/treasure.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_TREASURE_H
+#define MM1_DATA_TREASURE_H
+
+#include "common/serializer.h"
+
+namespace MM {
+namespace MM1 {
+
+enum ContainerType {
+ CLOTH_SACK = 0, LEATHER_SACK = 1, WOODEN_BOX = 2,
+ WOODEN_CHEST = 3, IRON_BOX = 4, IRON_CHEST = 5,
+ SILVER_BOX = 6, SILVER_CHEST = 7, GOLD_BOX = 8,
+ GOLD_CHEST = 9, BLACK_BOX = 10
+};
+
+class Treasure {
+private:
+ byte _data[TREASURE_COUNT];
+public:
+ byte &_container = _data[2];
+
+ Treasure() {
+ clear();
+ }
+
+ byte &operator[](uint i) {
+ assert(i < TREASURE_COUNT);
+ return _data[i];
+ }
+
+ void clear() {
+ Common::fill(&_data[0], &_data[TREASURE_COUNT], 0);
+ }
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 8de5a229f02..18ac6212423 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -31,6 +31,7 @@
#include "mm/mm1/data/items.h"
#include "mm/mm1/data/monsters.h"
#include "mm/mm1/data/roster.h"
+#include "mm/mm1/data/treasure.h"
#include "mm/mm1/game/encounter.h"
#include "mm/mm1/maps/maps.h"
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 483cf3dd489..6e1b42245ee 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -146,7 +146,7 @@ void Map03::special07() {
}
void Map03::special08() {
- g_globals->_treasure[2] = 9;
+ g_globals->_treasure._container = GOLD_CHEST;
g_globals->_treasure[5] = 200;
g_globals->_treasure[8] = 200;
g_events->addAction(KEYBIND_SEARCH);
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index f7cef090743..968ab833bc5 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -117,7 +117,7 @@ void Map08::special20() {
g_maps->clearSpecial();
g_globals->_treasure[5] = getRandomNumber(48);
g_globals->_treasure[1] = 1;
- g_globals->_treasure[2] = 6;
+ g_globals->_treasure._container = SILVER_BOX;
addTreasure();
}
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index bb88a38f88b..39356bc5c58 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -122,7 +122,7 @@ void Map10::special20() {
g_maps->clearSpecial();
g_globals->_treasure[5] = 252;
g_globals->_treasure[8] = 20;
- g_globals->_treasure[2] = 6;
+ g_globals->_treasure._container = SILVER_CHEST;
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index 4f45f5742f0..b3843258e87 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -165,7 +165,7 @@ void Map18::special09() {
g_maps->clearSpecial();
g_globals->_treasure[5] = 238;
g_globals->_treasure[1] = 4;
- g_globals->_treasure[2] = 4;
+ g_globals->_treasure._container = IRON_BOX;
g_globals->_treasure[6] = 96;
g_globals->_treasure[7] = 9;
g_events->addAction(KEYBIND_SEARCH);
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index 7af83534b4f..a7442264fec 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -177,7 +177,7 @@ void Map23::special12() {
void Map23::special13() {
g_maps->clearSpecial();
- g_globals->_treasure[2] = 4;
+ g_globals->_treasure._container = IRON_BOX;
g_globals->_treasure[3] = 171;
g_globals->_treasure[4] = 183;
g_globals->_treasure[5] = 191;
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index 784fe23069f..1943093c6c7 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -161,7 +161,7 @@ void Map37::special15() {
void Map37::special16() {
g_maps->clearSpecial();
- g_globals->_treasure[2] = 8;
+ g_globals->_treasure._container = GOLD_BOX;
g_globals->_treasure[8] = 100;
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
index 9d7cc3ccb59..3d432b1e888 100644
--- a/engines/mm/mm1/maps/map42.cpp
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -147,7 +147,7 @@ void Map42::special15() {
void Map42::special17() {
g_globals->_treasure[6] = 76;
g_globals->_treasure[7] = 29;
- g_globals->_treasure[2] = 8;
+ g_globals->_treasure._container = GOLD_BOX;
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 56270de9617..b37f3a13da9 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -36,6 +36,7 @@
#include "mm/mm1/views/character_info.h"
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/rest.h"
+#include "mm/mm1/views/search.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/views/locations/market.h"
@@ -87,6 +88,7 @@ private:
Views::Protect _protect;
Views::QuickRef _quickRef;
Views::Rest _rest;
+ Views::Search _search;
Views::Title _title;
Views::CharacterInfo _characterInfo;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index b41b4214e96..8d9f1d9e7d7 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -22,7 +22,6 @@
#include "mm/mm1/views/game.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/meta_engine.h"
-#include "mm/mm1/game/search.h"
namespace MM {
namespace MM1 {
@@ -63,7 +62,7 @@ bool Game::msgAction(const ActionMessage &msg) {
g_events->send(GameMessage("REST"));
return true;
case KEYBIND_SEARCH:
- MM1::Game::Search::execute();
+ addView("Search");
break;
case KEYBIND_VIEW_PARTY1:
case KEYBIND_VIEW_PARTY2:
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
new file mode 100644
index 00000000000..b23cd16fdfd
--- /dev/null
+++ b/engines/mm/mm1/views/search.cpp
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/search.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Search::Search() : TextView("Search") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Search::msgFocus(const FocusMessage &msg) {
+ _hasStuff = false;
+ for (int i = 0; i < 6 && !_hasStuff; ++i)
+ _hasStuff = g_globals->_treasure[i + 3] != 0;
+ _mode = INITIAL;
+
+ return true;
+}
+
+void Search::draw() {
+ clearSurface();
+
+ switch (_mode) {
+ case INITIAL:
+ if (!_hasStuff) {
+ Common::String line = STRING["views.search.search"] +
+ STRING["views.search.nothing"];
+ writeString(0, 1, line);
+ close();
+
+ } else {
+ Sound::sound(SOUND_2);
+ Common::String line = STRING["views.search.search"] +
+ STRING["views.search.you_found"];
+ writeString(0, 1, line);
+ delaySeconds(2);
+ }
+ break;
+
+ case OPTIONS:
+ break;
+ }
+}
+
+bool Search::msgKeypress(const KeypressMessage &msg) {
+ close();
+ return true;
+}
+
+void Search::timeout() {
+ Maps::Map &map = *g_maps->_currentMap;
+ _val1 = MIN(g_globals->_treasure._container * 8 +
+ map[Maps::MAP_48], 255);
+
+ if (!g_globals->_treasure[1]) {
+ g_globals->_treasure[1] = (getRandomNumber(100) < _val1) ? 1 : 2;
+ }
+
+ // Display a graphic for the container type
+ int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 4 : 2;
+ send("GameView", DrawGraphicMessage(gfxNum));
+
+ // Show the name of the container type in the game view
+ // TODO
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/search.cpp b/engines/mm/mm1/views/search.h
similarity index 66%
rename from engines/mm/mm1/game/search.cpp
rename to engines/mm/mm1/views/search.h
index 77a824e1f7a..4f70d48aa65 100644
--- a/engines/mm/mm1/game/search.cpp
+++ b/engines/mm/mm1/views/search.h
@@ -19,19 +19,33 @@
*
*/
-#include "mm/mm1/events.h"
-#include "mm/mm1/sound.h"
-#include "mm/mm1/game/search.h"
+#ifndef MM1_VIEWS_SEARCH_H
+#define MM1_VIEWS_SEARCH_H
+
+#include "mm/mm1/views/text_view.h"
namespace MM {
namespace MM1 {
-namespace Game {
+namespace Views {
+
+class Search : public TextView {
+private:
+ enum Mode { INITIAL, OPTIONS };
+ Mode _mode = INITIAL;
+ bool _hasStuff = false;
+ byte _val1 = 0;
+public:
+ Search();
+ virtual ~Search() {}
-void Search::execute() {
- // TODO: Handle properly
- g_events->send(InfoMessage("YOU FOUND... NOTHING"));
-}
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void timeout() override;
+};
-} // namespace Game
+} // namespace Views
} // namespace MM1
} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index dfa701072e5..f115c32e5b9 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -27,7 +27,6 @@ MODULE_OBJS := \
mm1/game/combat.o \
mm1/game/encounter.o \
mm1/game/rest.o \
- mm1/game/search.o \
mm1/game/spell_casting.o \
mm1/game/spells_party.o \
mm1/game/spells_monsters.o \
@@ -100,6 +99,7 @@ MODULE_OBJS := \
mm1/views/protect.o \
mm1/views/quick_ref.o \
mm1/views/rest.o \
+ mm1/views/search.o \
mm1/views/title.o \
mm1/views/text_entry.o \
mm1/views/text_view.o \
Commit: 322d01de64aac2919c4d410aba27e0ee5d01c6cc
https://github.com/scummvm/scummvm/commit/322d01de64aac2919c4d410aba27e0ee5d01c6cc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:30+01:00
Commit Message:
MM: MM1: Refactor game view business names code to allow arbitrary text
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/views/game_view.cpp
engines/mm/mm1/views/game_view.h
engines/mm/mm1/views/search.cpp
engines/mm/utils/strings_data.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index a6bf254aa2e..9ae5a41e2fb 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1507,7 +1507,7 @@ maps:
grate: "THE CRYSTAL GRATE REPELS YOU!"
map51:
- substance: 'WITHOUT EXPERIMENTAL SUBSTANCE\nTHERE IS NO HOPE...POOF!"
+ substance: "WITHOUT EXPERIMENTAL SUBSTANCE\nTHERE IS NO HOPE...POOF!"
map52:
summoned: "YOU HAVE BEEN SUMMONED...POOF!"
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 0d24ea944d6..6d0fff58354 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -100,7 +100,8 @@ bool ViewBase::msgAction(const ActionMessage &msg) {
}
bool ViewBase::msgValue(const ValueMessage &msg) {
- _businessDisplay = msg._value;
+ _descriptionLine = STRING[Common::String::format(
+ "dialogs.location.titles.%d", msg._value)];
draw();
return true;
}
@@ -117,6 +118,9 @@ bool ViewBase::msgGame(const GameMessage &msg) {
replaceView("Game");
update();
return true;
+ } else {
+ _descriptionLine = msg._name;
+ draw();
}
return TextView::msgGame(msg);
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 1b29357f045..33438f0393a 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -37,8 +37,8 @@ class ViewBase : public Views::TextView {
protected:
bool _isDark = false;
Common::String _dialogMessage;
- int _businessDisplay = -1;
bool _stepRandom = false;
+ Common::String _descriptionLine;
private:
/**
* Turn left
diff --git a/engines/mm/mm1/views/game_view.cpp b/engines/mm/mm1/views/game_view.cpp
index 1398868eb56..579b5af0323 100644
--- a/engines/mm/mm1/views/game_view.cpp
+++ b/engines/mm/mm1/views/game_view.cpp
@@ -64,8 +64,8 @@ void GameView::draw() {
writeString(9, 7, STRING["view.darkness"]);
}
- if (_businessDisplay != -1)
- drawBusinessName();
+ if (!_descriptionLine.empty())
+ drawDescriptionLine();
}
void GameView::drawScene() {
@@ -201,10 +201,9 @@ void GameView::drawDialogMessage() {
writeString(9, 8, " ");
}
-void GameView::drawBusinessName() {
- writeString(10, 15, STRING[Common::String::format(
- "dialogs.location.titles.%d", _businessDisplay)]);
- _businessDisplay = -1;
+void GameView::drawDescriptionLine() {
+ writeString(10, 15, _descriptionLine);
+ _descriptionLine.clear();
}
} // namespace Views
diff --git a/engines/mm/mm1/views/game_view.h b/engines/mm/mm1/views/game_view.h
index 1b344e443ed..9184c85dd2f 100644
--- a/engines/mm/mm1/views/game_view.h
+++ b/engines/mm/mm1/views/game_view.h
@@ -51,9 +51,10 @@ private:
void drawDialogMessage();
/**
- * Draws the business name line
+ * Draws a business name or other information like
+ * container container for searches
*/
- void drawBusinessName();
+ void drawDescriptionLine();
public:
GameView(UIElement *owner);
virtual ~GameView() {}
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index b23cd16fdfd..541c35ffefc 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -84,7 +84,10 @@ void Search::timeout() {
send("GameView", DrawGraphicMessage(gfxNum));
// Show the name of the container type in the game view
- // TODO
+ send("GameView", GameMessage(
+ STRING[Common::String::format("views.search.containers.%d",
+ g_globals->_treasure._container)]
+ ));
}
} // namespace Views
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
index cf35207629c..270abdf7c45 100644
--- a/engines/mm/utils/strings_data.cpp
+++ b/engines/mm/utils/strings_data.cpp
@@ -83,7 +83,8 @@ bool StringsData::load(const Common::String &filename) {
value.deleteChar(i);
value.deleteChar(i);
value.setChar((char)hexToInt(hex), i);
- } else if (value[i] == '"' && value[i + 1] == '"') {
+ } else if (value[i] == '"' && i < (value.size() - 1) &&
+ value[i + 1] == '"') {
value.deleteChar(i);
}
}
Commit: cde86c909fcb3ad792b307b8c88724d8bc4a04f3
https://github.com/scummvm/scummvm/commit/cde86c909fcb3ad792b307b8c88724d8bc4a04f3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:30+01:00
Commit Message:
MM: MM1: Fix display of search nothing, added treasure methods
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/data/treasure.cpp
engines/mm/mm1/data/treasure.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/search.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9ae5a41e2fb..b10ca0745a5 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -153,6 +153,9 @@
8: " GOLD BOX "
9: " GOLD CHEST "
10: " BLACK BOX "
+ options1: "OPTIONS: 1) OPEN IT"
+ options2: "2) FIND/REMOVE TRAP"
+ options3: "3) DETECT MAGIC/TRAP"
statues:
stone: "ON THIS STONE STATUE OF "
plaque: "A PLAQUE READS..."
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 64bab7a7a5b..08a79cc56d5 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -29,8 +29,6 @@
namespace MM {
namespace MM1 {
-#define TREASURE_COUNT 9
-
enum ItemId {
GARLIC_ID = 175,
WOLFSBANE_ID = 176,
diff --git a/engines/mm/mm1/data/treasure.cpp b/engines/mm/mm1/data/treasure.cpp
index 4703a840654..875668061cc 100644
--- a/engines/mm/mm1/data/treasure.cpp
+++ b/engines/mm/mm1/data/treasure.cpp
@@ -19,10 +19,32 @@
*
*/
+#include "common/algorithm.h"
#include "mm/mm1/data/treasure.h"
namespace MM {
namespace MM1 {
+#define TREASURE_COUNT 6
+#define ARRAY_COUNT (TREASURE_COUNT + 3)
+
+void Treasure::clear() {
+ Common::fill(&_data[0], &_data[ARRAY_COUNT], 0);
+}
+
+byte &Treasure::operator[](uint i) {
+ assert(i < ARRAY_COUNT);
+ return _data[i];
+}
+
+bool Treasure::present() const {
+ for (int i = 0; i < TREASURE_COUNT; ++i) {
+ if (_data[i + 3])
+ return true;
+ }
+
+ return false;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
index f4f5e4cd71f..8203b140048 100644
--- a/engines/mm/mm1/data/treasure.h
+++ b/engines/mm/mm1/data/treasure.h
@@ -22,7 +22,7 @@
#ifndef MM1_DATA_TREASURE_H
#define MM1_DATA_TREASURE_H
-#include "common/serializer.h"
+#include "common/scummsys.h"
namespace MM {
namespace MM1 {
@@ -36,7 +36,7 @@ enum ContainerType {
class Treasure {
private:
- byte _data[TREASURE_COUNT];
+ byte _data[9];
public:
byte &_container = _data[2];
@@ -44,14 +44,17 @@ public:
clear();
}
- byte &operator[](uint i) {
- assert(i < TREASURE_COUNT);
- return _data[i];
- }
+ byte &operator[](uint i);
- void clear() {
- Common::fill(&_data[0], &_data[TREASURE_COUNT], 0);
- }
+ /**
+ * Clears the treasure list
+ */
+ void clear();
+
+ /**
+ * Returns true if any treasure has been assigned
+ */
+ bool present() const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 8d9f1d9e7d7..1595741a8b0 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -62,7 +62,8 @@ bool Game::msgAction(const ActionMessage &msg) {
g_events->send(GameMessage("REST"));
return true;
case KEYBIND_SEARCH:
- addView("Search");
+ //g_globals->_treasure[5] = 240; //***DEBUG***
+ send("Search", GameMessage("SHOW"));
break;
case KEYBIND_VIEW_PARTY1:
case KEYBIND_VIEW_PARTY2:
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 541c35ffefc..ec5d68ffda3 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -31,42 +31,71 @@ Search::Search() : TextView("Search") {
_bounds = getLineBounds(20, 24);
}
+bool Search::msgGame(const GameMessage &msg) {
+ if (msg._name != "SHOW")
+ return false;
+
+ bool hasStuff = g_globals->_treasure.present();
+ if (hasStuff) {
+ // Focus view to show what was found
+ open();
+
+ } else {
+ // Otherwise send an info message to say nothing was found
+ Common::String line = STRING["dialogs.search.search"] +
+ STRING["dialogs.search.nothing"];
+ send(InfoMessage(0, 1, line));
+ }
+
+ return true;
+}
+
bool Search::msgFocus(const FocusMessage &msg) {
- _hasStuff = false;
- for (int i = 0; i < 6 && !_hasStuff; ++i)
- _hasStuff = g_globals->_treasure[i + 3] != 0;
_mode = INITIAL;
-
return true;
}
void Search::draw() {
+ Common::String line;
clearSurface();
switch (_mode) {
case INITIAL:
- if (!_hasStuff) {
- Common::String line = STRING["views.search.search"] +
- STRING["views.search.nothing"];
- writeString(0, 1, line);
- close();
-
- } else {
- Sound::sound(SOUND_2);
- Common::String line = STRING["views.search.search"] +
- STRING["views.search.you_found"];
- writeString(0, 1, line);
- delaySeconds(2);
- }
+ Sound::sound(SOUND_2);
+ line = STRING["dialogs.search.search"] +
+ STRING["dialogs.search.you_found"];
+ writeString(0, 1, line);
+ delaySeconds(3);
break;
case OPTIONS:
+ writeString(1, 1, STRING["dialogs.search.options1"]);
+ writeString(20, 2, STRING["dialogs.search.options2"]);
+ writeString(20, 3, STRING["dialogs.search.options3"]);
+ escToGoBack(0, 3);
break;
}
}
bool Search::msgKeypress(const KeypressMessage &msg) {
- close();
+ switch (_mode) {
+ case INITIAL:
+ cancelDelay();
+ timeout();
+ break;
+
+ case OPTIONS:
+ switch (msg.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ close();
+ break;
+ case Common::KEYCODE_1:
+ // TODO: 1, 2, 3
+ break;
+ }
+ break;
+ }
+
return true;
}
@@ -88,6 +117,9 @@ void Search::timeout() {
STRING[Common::String::format("views.search.containers.%d",
g_globals->_treasure._container)]
));
+
+ _mode = OPTIONS;
+ draw();
}
} // namespace Views
diff --git a/engines/mm/mm1/views/search.h b/engines/mm/mm1/views/search.h
index 4f70d48aa65..db4bfef0303 100644
--- a/engines/mm/mm1/views/search.h
+++ b/engines/mm/mm1/views/search.h
@@ -32,12 +32,12 @@ class Search : public TextView {
private:
enum Mode { INITIAL, OPTIONS };
Mode _mode = INITIAL;
- bool _hasStuff = false;
byte _val1 = 0;
public:
Search();
virtual ~Search() {}
+ bool msgGame(const GameMessage &msg) override;
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index f115c32e5b9..5c30fde542d 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -23,6 +23,7 @@ MODULE_OBJS := \
mm1/data/party.o \
mm1/data/roster.o \
mm1/data/text_parser.o \
+ mm1/data/treasure.o \
mm1/game/game_logic.o \
mm1/game/combat.o \
mm1/game/encounter.o \
Commit: f19e3781ebed971203f0e9b9378914b36ac0180a
https://github.com/scummvm/scummvm/commit/f19e3781ebed971203f0e9b9378914b36ac0180a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:30+01:00
Commit Message:
MM: MM1: Fix display of container type text in view area
Changed paths:
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map54.cpp
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/maps/alamar.cpp
engines/mm/mm1/views/search.cpp
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 203505ce796..e48e0e0a5d9 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -97,7 +97,7 @@ void Map35::special04() {
void Map35::special05() {
updateFlags();
- send("GameView", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7));
g_events->addView("Inspectron");
}
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index 2981d92c975..720a2df6e4f 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -94,7 +94,7 @@ void Map36::special04() {
void Map36::special05() {
updateFlags();
- send("GameView", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7));
g_events->addView("Hacker");
}
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index de4d2c69ba9..eba213242a2 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -105,7 +105,7 @@ void Map43::special04() {
void Map43::special05() {
updateFlags();
- send("GameView", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7));
g_events->addView("LordIronfist");
}
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index 4fa2051f808..936de45ae9c 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -106,7 +106,7 @@ void Map49::special06() {
g_maps->changeMap(0x412, 3);
} else {
- send("GameView", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7));
g_events->addView("Alamar");
}
}
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index cdd0600317b..27cb0ceef56 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -111,7 +111,7 @@ void Map54::special06() {
}
void Map54::special07() {
- send("GameView", DrawGraphicMessage(5));
+ send("View", DrawGraphicMessage(5));
g_events->addView("Keeper");
}
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 1595741a8b0..9d5308288ff 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -62,7 +62,7 @@ bool Game::msgAction(const ActionMessage &msg) {
g_events->send(GameMessage("REST"));
return true;
case KEYBIND_SEARCH:
- //g_globals->_treasure[5] = 240; //***DEBUG***
+ g_globals->_treasure[5] = 240; //***DEBUG***
send("Search", GameMessage("SHOW"));
break;
case KEYBIND_VIEW_PARTY1:
diff --git a/engines/mm/mm1/views/maps/alamar.cpp b/engines/mm/mm1/views/maps/alamar.cpp
index fdd3c363eed..12ee022c7c9 100644
--- a/engines/mm/mm1/views/maps/alamar.cpp
+++ b/engines/mm/mm1/views/maps/alamar.cpp
@@ -66,8 +66,8 @@ void Alamar::draw() {
} else if (map[HAS_EYE]) {
close();
map.redrawGame();
- send("GameView", DrawGraphicMessage(7));
- send("GameView", DrawGraphicMessage(6));
+ send("View", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(6));
clearSurface();
writeString(0, 0, STRING["maps.map49.alamar1"]);
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index ec5d68ffda3..77a68015367 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -65,7 +65,7 @@ void Search::draw() {
line = STRING["dialogs.search.search"] +
STRING["dialogs.search.you_found"];
writeString(0, 1, line);
- delaySeconds(3);
+ delaySeconds(2);
break;
case OPTIONS:
@@ -110,11 +110,11 @@ void Search::timeout() {
// Display a graphic for the container type
int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 4 : 2;
- send("GameView", DrawGraphicMessage(gfxNum));
+ send("View", DrawGraphicMessage(gfxNum));
// Show the name of the container type in the game view
- send("GameView", GameMessage(
- STRING[Common::String::format("views.search.containers.%d",
+ send("View", GameMessage(
+ STRING[Common::String::format("dialogs.search.containers.%d",
g_globals->_treasure._container)]
));
Commit: 5b96f31fcb350faffd3b4dbda7c3c7fd962cf928
https://github.com/scummvm/scummvm/commit/5b96f31fcb350faffd3b4dbda7c3c7fd962cf928
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: Fix display of search container graphic, map classes graphics
Changed paths:
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map54.cpp
engines/mm/mm1/views/search.cpp
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index e48e0e0a5d9..8edac8894d9 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -97,7 +97,7 @@ void Map35::special04() {
void Map35::special05() {
updateFlags();
- send("View", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7 + 65));
g_events->addView("Inspectron");
}
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index 720a2df6e4f..98884b3760f 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -94,7 +94,7 @@ void Map36::special04() {
void Map36::special05() {
updateFlags();
- send("View", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7 + 65));
g_events->addView("Hacker");
}
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index eba213242a2..822616a21de 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -105,7 +105,7 @@ void Map43::special04() {
void Map43::special05() {
updateFlags();
- send("View", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7 + 65));
g_events->addView("LordIronfist");
}
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index 936de45ae9c..4e4d1bb8ba3 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -106,7 +106,7 @@ void Map49::special06() {
g_maps->changeMap(0x412, 3);
} else {
- send("View", DrawGraphicMessage(7));
+ send("View", DrawGraphicMessage(7 + 65));
g_events->addView("Alamar");
}
}
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index 27cb0ceef56..5d711addedd 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -111,7 +111,7 @@ void Map54::special06() {
}
void Map54::special07() {
- send("View", DrawGraphicMessage(5));
+ send("View", DrawGraphicMessage(5 + 65));
g_events->addView("Keeper");
}
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 77a68015367..a247c5aa15f 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -108,16 +108,16 @@ void Search::timeout() {
g_globals->_treasure[1] = (getRandomNumber(100) < _val1) ? 1 : 2;
}
- // Display a graphic for the container type
- int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 4 : 2;
- send("View", DrawGraphicMessage(gfxNum));
-
// Show the name of the container type in the game view
send("View", GameMessage(
STRING[Common::String::format("dialogs.search.containers.%d",
g_globals->_treasure._container)]
));
+ // Display a graphic for the container type
+ int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 4 : 2;
+ send("View", DrawGraphicMessage(gfxNum + 65));
+
_mode = OPTIONS;
draw();
}
Commit: 479411d0eb526f4c9edcf632955e9ab8db7ffeef
https://github.com/scummvm/scummvm/commit/479411d0eb526f4c9edcf632955e9ab8db7ffeef
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: More implementing Search dialog
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/treasure.h
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/search.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index b10ca0745a5..4cc2b2fb709 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -156,6 +156,11 @@
options1: "OPTIONS: 1) OPEN IT"
options2: "2) FIND/REMOVE TRAP"
options3: "3) DETECT MAGIC/TRAP"
+ bad_class: "*** BAD CLASS ***"
+ no_sp: "*** NO SPELL POINTS ***"
+ magic_trap: "MAGIC (%c) TRAP (%c)"
+ who_will_try: "WHO WILL TRY '1'-'%c'"
+ check_condition: "*** CHECK CONDITION ***"
statues:
stone: "ON THIS STONE STATUE OF "
plaque: "A PLAQUE READS..."
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 6a861ab2b93..37e492ba375 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -355,6 +355,9 @@ struct AttributePair16 {
_base = _current = v;
return *this;
}
+ operator uint16() const {
+ return _current;
+ }
void synchronize(Common::Serializer &s) {
s.syncAsUint16LE(_base);
s.syncAsUint16LE(_current);
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
index 8203b140048..c1206791761 100644
--- a/engines/mm/mm1/data/treasure.h
+++ b/engines/mm/mm1/data/treasure.h
@@ -38,6 +38,7 @@ class Treasure {
private:
byte _data[9];
public:
+ byte &_trapType = _data[1];
byte &_container = _data[2];
Treasure() {
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index a247c5aa15f..2970c7a4c7a 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -90,8 +90,44 @@ bool Search::msgKeypress(const KeypressMessage &msg) {
close();
break;
case Common::KEYCODE_1:
- // TODO: 1, 2, 3
+ openContainer();
break;
+ case Common::KEYCODE_2:
+ findRemoveTrap();
+ break;
+ case Common::KEYCODE_3:
+ detectMagicTrap();
+ break;
+ }
+ break;
+
+ case RESPONSE:
+ if (isDelayActive()) {
+ cancelDelay();
+ timeout();
+ }
+ break;
+
+ case WHO_WILL_TRY:
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ _mode = OPTIONS;
+ draw();
+
+ } else if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= (Common::KEYCODE_0 + (int)g_globals->_party.size())) {
+ // Character selected
+ g_globals->_currCharacter = &g_globals->_party[
+ msg.keycode - Common::KEYCODE_1];
+ if ((g_globals->_currCharacter->_condition &
+ (BAD_CONDITION | DEAD | STONE | ASLEEP)) != 0) {
+ clearSurface();
+ writeString(3, 2, STRING["dialogs.search.check_condition"]);
+ delaySeconds(4);
+ } else if (_removing) {
+ findRemoveTrap2();
+ } else {
+ openContainer2();
+ }
}
break;
}
@@ -100,26 +136,109 @@ bool Search::msgKeypress(const KeypressMessage &msg) {
}
void Search::timeout() {
- Maps::Map &map = *g_maps->_currentMap;
- _val1 = MIN(g_globals->_treasure._container * 8 +
- map[Maps::MAP_48], 255);
+ switch (_mode) {
+ case INITIAL: {
+ Maps::Map &map = *g_maps->_currentMap;
+ _val1 = MIN(g_globals->_treasure._container * 8 +
+ map[Maps::MAP_48], 255);
+
+ if (!g_globals->_treasure[1]) {
+ g_globals->_treasure[1] = (getRandomNumber(100) < _val1) ? 1 : 2;
+ }
- if (!g_globals->_treasure[1]) {
- g_globals->_treasure[1] = (getRandomNumber(100) < _val1) ? 1 : 2;
+ // Show the name of the container type in the game view
+ send("View", GameMessage(
+ STRING[Common::String::format("dialogs.search.containers.%d",
+ g_globals->_treasure._container)]
+ ));
+
+ // Display a graphic for the container type
+ int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 4 : 2;
+ send("View", DrawGraphicMessage(gfxNum + 65));
+
+ _mode = OPTIONS;
+ draw();
+ break;
}
+ case RESPONSE:
+ _mode = OPTIONS;
+ draw();
+ break;
- // Show the name of the container type in the game view
- send("View", GameMessage(
- STRING[Common::String::format("dialogs.search.containers.%d",
- g_globals->_treasure._container)]
- ));
+ case WHO_WILL_TRY:
+ draw();
+ break;
+ }
+}
+
+void Search::openContainer() {
+ _removing = false;
+ if (!whoWillTry())
+ openContainer2();
+}
- // Display a graphic for the container type
- int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 4 : 2;
- send("View", DrawGraphicMessage(gfxNum + 65));
+void Search::openContainer2() {
+
+}
- _mode = OPTIONS;
- draw();
+void Search::findRemoveTrap() {
+ _removing = true;
+ if (!whoWillTry())
+ findRemoveTrap2();
+}
+
+void Search::findRemoveTrap2() {
+ Character &c = *g_globals->_currCharacter;
+
+ if (g_globals->_treasure._trapType == 1) {
+ byte val = c._v6c;
+ if (getRandomNumber(val >= 100 ? val + 5 : 100) >= val) {
+ // TODO
+ }
+ }
+}
+
+void Search::detectMagicTrap() {
+ Character &c = *g_globals->_currCharacter;
+ _mode = RESPONSE;
+
+ if (c._class == PALADIN || c._class == CLERIC) {
+ Sound::sound(SOUND_2);
+ clearSurface();
+ writeString(6, 2, STRING["dialogs.search.bad_class"]);
+ delaySeconds(4);
+
+ } else if (c._sp == 0) {
+ Sound::sound(SOUND_2);
+ clearSurface();
+ writeString(6, 2, STRING["dialogs.search.no_sp"]);
+ delaySeconds(4);
+
+ } else {
+ c._sp._current--;
+ char magic = g_globals->_treasure[3] || g_globals->_treasure[4]
+ || g_globals->_treasure[5] || g_globals->_treasure[8] ? 'Y' : 'N';
+ char trapped = g_globals->_treasure._trapType == 1 ? 'Y' : 'N';
+
+ clearSurface();
+ writeString(5, 1, Common::String::format(
+ STRING["dialogs.search.magic_trap"].c_str(),
+ magic, trapped));
+
+ delaySeconds(8);
+ }
+}
+
+bool Search::whoWillTry() {
+ if (g_globals->_party.size() == 1) {
+ g_globals->_currCharacter = &g_globals->_party[0];
+ return true;
+ } else {
+ // Switch to mode to ask which character to use
+ _mode = WHO_WILL_TRY;
+ draw();
+ return false;
+ }
}
} // namespace Views
diff --git a/engines/mm/mm1/views/search.h b/engines/mm/mm1/views/search.h
index db4bfef0303..c8c26789abe 100644
--- a/engines/mm/mm1/views/search.h
+++ b/engines/mm/mm1/views/search.h
@@ -30,9 +30,30 @@ namespace Views {
class Search : public TextView {
private:
- enum Mode { INITIAL, OPTIONS };
+ enum Mode { INITIAL, OPTIONS, RESPONSE, WHO_WILL_TRY };
Mode _mode = INITIAL;
+ bool _removing = false;
byte _val1 = 0;
+
+ /**
+ * Open the container
+ */
+ void openContainer();
+ void openContainer2();
+
+ /**
+ * Find/remove trap
+ */
+ void findRemoveTrap();
+ void findRemoveTrap2();
+
+ /**
+ * Detect magic/trap
+ */
+ void detectMagicTrap();
+
+ bool whoWillTry();
+
public:
Search();
virtual ~Search() {}
Commit: 771a642f3ce539e9cb5e32816504b6cfaad96332
https://github.com/scummvm/scummvm/commit/771a642f3ce539e9cb5e32816504b6cfaad96332
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: Shifted checkPartyDead method to Party class
Changed paths:
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index b09a797e55e..1f308cd77f1 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -102,5 +102,18 @@ bool Party::hasItem(byte itemId) const {
return false;
}
+bool Party::checkPartyDead() const {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ if (!(c._condition & (ASLEEP | STONE | DEAD | BAD_CONDITION)))
+ return false;
+ }
+
+ // At this point, there's no good characters.
+ // So redirect to the death screen
+ g_events->replaceView("Dead");
+ return true;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index ee7517a0e35..ea68c15baa4 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -70,6 +70,12 @@ struct Party : public Common::Array<Character> {
* Returns true if any of the party has an item
*/
bool hasItem(byte itemId) const;
+
+ /**
+ * Checks whether the party is dead or out of action,
+ * and if so, switches to the death screen
+ */
+ bool checkPartyDead() const;
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 6d0fff58354..042b63ec188 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -66,7 +66,7 @@ darkness:
_stepRandom = false;
g_globals->_encounters.execute();
} else {
- map.checkPartyDead();
+ g_globals->_party.checkPartyDead();
}
// Flag to redraw the screen
@@ -202,12 +202,12 @@ void ViewBase::backwards() {
if (!g_globals->_intangible) {
if (maps._currentWalls & maps._backwardsMask) {
Sound::sound(SOUND_1);
- map.checkPartyDead();
+ g_globals->_party.checkPartyDead();
return;
}
if (maps._currentState & 0x55 & maps._backwardsMask) {
Sound::sound(SOUND_1);
- map.checkPartyDead();
+ g_globals->_party.checkPartyDead();
return;
}
}
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index e40254185e4..1f803c8d7f0 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -79,16 +79,8 @@ void Map::loadOverlay() {
f.read(&_data[0], dataSize);
}
-void Map::checkPartyDead() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- if ((c._condition & (ASLEEP | STONE | DEAD | BAD_CONDITION)) == 0)
- return;
- }
-
- // At this point, there's no good characters.
- // So redirect to the death screen
- g_events->replaceView("Dead");
+bool Map::checkPartyDead() {
+ return g_globals->_party.checkPartyDead();
}
uint16 Map::dataWord(uint16 ofs) const {
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 67857ea1504..4f93f734dac 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -176,7 +176,7 @@ public:
* Checks whether the party is dead or out of action,
* and if so, switches to the death screen
*/
- void checkPartyDead();
+ bool checkPartyDead();
/**
* Send a message to a UI element
Commit: c248428c6acdd432b9f30fffec3a06d0502e94fb
https://github.com/scummvm/scummvm/commit/c248428c6acdd432b9f30fffec3a06d0502e94fb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: In progress Unlock view
Changed paths:
A engines/mm/mm1/views/unlock.cpp
A engines/mm/mm1/views/unlock.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/search.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 4cc2b2fb709..42b977b8830 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -248,6 +248,10 @@
congrats: "CONGRATULATIONS! YOU ARE NOW LEVEL "
hp: "YOU GAINED %d HIT POINTS"
new_spells: "YOU GAINED NEW SPELLS!"
+ unlock:
+ who_will_try: "WHO WILL TRY '1'-'%c'?"
+ success: "SUCCESS!"
+ failed: "UNLOCK FAILED!"
view_characters:
title: "VIEW ALL CHARACTERS"
legend1: "'A'-'%c' TO VIEW A CHARACTER"
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index ae1cadbbf10..e9ddd7116a6 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -232,6 +232,10 @@ void UIElement::close() {
g_engine->popView();
}
+bool UIElement::isFocused() const {
+ return g_events->focusedView() == this;
+}
+
void UIElement::clearSurface() {
Graphics::ManagedSurface s = getSurface();
s.fillRect(Common::Rect(s.w, s.h), 0);
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 49e7462daea..0dfdaed4339 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -146,6 +146,11 @@ public:
*/
void close();
+ /*
+ * Returns true if the view is focused
+ */
+ bool isFocused() const;
+
/**
* Sets the focus to a new view
*/
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 042b63ec188..4aa495ce4cd 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -277,7 +277,7 @@ void ViewBase::bash() {
}
// Check for trap being triggered
- if (g_engine->getRandomNumber(100) >= map[Maps::MAP_48]) {
+ if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DARTS_THRESHOLD]) {
warning("TODO: trigger trap");
} else {
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 4f93f734dac..bfed2c216f0 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -80,7 +80,8 @@ enum DataOffset {
MAP_45 = 45,
MAP_FLAGS = 46,
MAP_47 = 47,
- MAP_48 = 48
+ MAP_DARTS_THRESHOLD = 48,
+ MAP_UNLOCK_THRESHOLD = 49
};
enum WallType {
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index b37f3a13da9..4a3204560b9 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -37,6 +37,7 @@
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/rest.h"
#include "mm/mm1/views/search.h"
+#include "mm/mm1/views/unlock.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
#include "mm/mm1/views/locations/market.h"
@@ -90,6 +91,7 @@ private:
Views::Rest _rest;
Views::Search _search;
Views::Title _title;
+ Views::Unlock _unlock;
Views::CharacterInfo _characterInfo;
Views::Locations::Blacksmith _blacksmith;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 9d5308288ff..88356e2a867 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -65,6 +65,9 @@ bool Game::msgAction(const ActionMessage &msg) {
g_globals->_treasure[5] = 240; //***DEBUG***
send("Search", GameMessage("SHOW"));
break;
+ case KEYBIND_UNLOCK:
+ send("Unlock", GameMessage("SHOW"));
+ break;
case KEYBIND_VIEW_PARTY1:
case KEYBIND_VIEW_PARTY2:
case KEYBIND_VIEW_PARTY3:
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 2970c7a4c7a..04c46ff1252 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -140,7 +140,7 @@ void Search::timeout() {
case INITIAL: {
Maps::Map &map = *g_maps->_currentMap;
_val1 = MIN(g_globals->_treasure._container * 8 +
- map[Maps::MAP_48], 255);
+ map[Maps::MAP_DARTS_THRESHOLD], 255);
if (!g_globals->_treasure[1]) {
g_globals->_treasure[1] = (getRandomNumber(100) < _val1) ? 1 : 2;
diff --git a/engines/mm/mm1/views/unlock.cpp b/engines/mm/mm1/views/unlock.cpp
new file mode 100644
index 00000000000..a4814ef1873
--- /dev/null
+++ b/engines/mm/mm1/views/unlock.cpp
@@ -0,0 +1,133 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/unlock.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Unlock::Unlock() : TextView("Unlock") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Unlock::msgGame(const GameMessage &msg) {
+ if (msg._name != "SHOW")
+ return false;
+ byte walls = g_maps->_currentWalls & g_maps->_forwardMask;
+
+ if (!(g_maps->_currentState & 0x55 & g_maps->_forwardMask) || !walls) {
+ g_globals->_party.checkPartyDead();
+ return true;
+ }
+
+ int offset;
+ if (!(walls & 0x55)) {
+ offset = 1;
+ } else if (!(walls & 0xaa)) {
+ offset = 0;
+ } else {
+ offset = 2;
+ }
+
+ if (g_maps->_currentMap->dataByte(30 + offset) != 1) {
+ g_globals->_party.checkPartyDead();
+ return true;
+ }
+
+ if (g_globals->_party.size() > 1) {
+ // Select the character to use
+ open();
+ } else {
+ // With only one party member, they're automatically used
+ charSelected(0);
+ }
+
+ return true;
+}
+
+bool Unlock::msgFocus(const FocusMessage &msg) {
+ return true;
+}
+
+void Unlock::draw() {
+ clearSurface();
+
+ writeString(4, 1, Common::String::format(
+ STRING["dialogs.unlock.who_will_try"].c_str(),
+ '0' + g_globals->_party.size()));
+ escToGoBack(0, 3);
+}
+
+bool Unlock::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ close();
+
+ } else if (msg.keycode >= Common::KEYCODE_1 &&
+ msg.keycode <= (Common::KEYCODE_0 + (int)g_globals->_party.size())) {
+ // Character selected
+ charSelected(msg.keycode - Common::KEYCODE_1);
+ }
+
+ return true;
+}
+
+void Unlock::charSelected(uint charIndex) {
+ Character &c = g_globals->_party[charIndex];
+ g_globals->_currCharacter = &c;
+
+ if (c._condition & (BAD_CONDITION | DEAD | STONE | ASLEEP)) {
+ Sound::sound(SOUND_2);
+ draw();
+
+ } else {
+ if (isFocused())
+ close();
+
+ int val = g_maps->_currentMap->dataByte(Maps::MAP_UNLOCK_THRESHOLD) * 4 +
+ getRandomNumber(100);
+
+ if (val < c._v6c) {
+ g_maps->_currentState =
+ g_maps->_currentMap->_walls[g_maps->_mapOffset] ^=
+ g_maps->_forwardMask & 0x55;
+
+ send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
+
+ } else if (getRandomNumber(100) <
+ g_maps->_currentMap->dataByte(Maps::MAP_DARTS_THRESHOLD)) {
+ send(InfoMessage(8, 1, STRING["dialogs.unlock.failed"]));
+
+ } else {
+ g_maps->_currentState =
+ g_maps->_currentMap->_walls[g_maps->_mapOffset] ^=
+ g_maps->_forwardMask & 0x55;
+ // TODO
+ warning("TODO: Darts triggered");
+ }
+ }
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/unlock.h b/engines/mm/mm1/views/unlock.h
new file mode 100644
index 00000000000..b02e956b4fe
--- /dev/null
+++ b/engines/mm/mm1/views/unlock.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_UNLOCK_H
+#define MM1_VIEWS_UNLOCK_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Unlock : public TextView {
+private:
+ void charSelected(uint charIndex);
+public:
+ Unlock();
+ virtual ~Unlock() {}
+
+ bool msgGame(const GameMessage &msg) override;
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 5c30fde542d..1905314dc50 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -104,6 +104,7 @@ MODULE_OBJS := \
mm1/views/title.o \
mm1/views/text_entry.o \
mm1/views/text_view.o \
+ mm1/views/unlock.o \
mm1/views_enh/button_container.o \
mm1/views_enh/character_info.o \
mm1/views_enh/dialogs.o \
Commit: 8f56425493cbf5ae25c5b017a43027520678ba3a
https://github.com/scummvm/scummvm/commit/8f56425493cbf5ae25c5b017a43027520678ba3a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: Fixes for unlocking view
Changed paths:
engines/mm/mm1/views/unlock.cpp
diff --git a/engines/mm/mm1/views/unlock.cpp b/engines/mm/mm1/views/unlock.cpp
index a4814ef1873..23a8742dfc9 100644
--- a/engines/mm/mm1/views/unlock.cpp
+++ b/engines/mm/mm1/views/unlock.cpp
@@ -109,7 +109,7 @@ void Unlock::charSelected(uint charIndex) {
if (val < c._v6c) {
g_maps->_currentState =
- g_maps->_currentMap->_walls[g_maps->_mapOffset] ^=
+ g_maps->_currentMap->_states[g_maps->_mapOffset] ^=
g_maps->_forwardMask & 0x55;
send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
@@ -120,7 +120,7 @@ void Unlock::charSelected(uint charIndex) {
} else {
g_maps->_currentState =
- g_maps->_currentMap->_walls[g_maps->_mapOffset] ^=
+ g_maps->_currentMap->_states[g_maps->_mapOffset] ^=
g_maps->_forwardMask & 0x55;
// TODO
warning("TODO: Darts triggered");
Commit: cf7929fc80bd3b8a5123a75019b67f5b595eaa78
https://github.com/scummvm/scummvm/commit/cf7929fc80bd3b8a5123a75019b67f5b595eaa78
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: Fix maps mixing up map _walls and _states
Changed paths:
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map21.cpp
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/maps/map27.cpp
engines/mm/mm1/maps/map29.cpp
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/map31.cpp
engines/mm/mm1/maps/map32.cpp
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/map52.cpp
engines/mm/mm1/views/maps/access_code.cpp
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index bdd2b388d35..827f41e91f0 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -48,7 +48,7 @@ void Map20::special() {
}
}
- if (_states[g_maps->_mapOffset] != 0xff) {
+ if (_walls[g_maps->_mapOffset] != 0xff) {
g_maps->clearSpecial();
enc.execute();
diff --git a/engines/mm/mm1/maps/map21.cpp b/engines/mm/mm1/maps/map21.cpp
index f65221eaf39..2948b0d59b8 100644
--- a/engines/mm/mm1/maps/map21.cpp
+++ b/engines/mm/mm1/maps/map21.cpp
@@ -50,7 +50,7 @@ void Map21::special() {
}
}
- if (_states[g_maps->_mapOffset] != 0xff) {
+ if (_walls[g_maps->_mapOffset] != 0xff) {
g_maps->clearSpecial();
enc.execute();
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index a7442264fec..23d31edd31e 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -169,8 +169,8 @@ void Map23::special11() {
void Map23::special12() {
send(SoundMessage(14, 22, STRING["maps.map23.avalanche"]));
g_maps->_currentState = 209;
- _walls[g_maps->_mapOffset] = 0xff;
- _states[g_maps->_mapOffset] = 162;
+ _states[g_maps->_mapOffset] = 0xff;
+ _walls[g_maps->_mapOffset] = 162;
g_maps->clearSpecial();
}
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index 84a08b468ea..41d14dbf6b6 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -44,7 +44,7 @@ void Map25::special() {
}
}
- switch (_states[g_maps->_mapOffset]) {
+ switch (_walls[g_maps->_mapOffset]) {
case 0:
if (getRandomNumber(100) == 100) {
Game::Encounter &enc = g_globals->_encounters;
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
index a48e66ffa23..06db321b65f 100644
--- a/engines/mm/mm1/maps/map27.cpp
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -44,7 +44,12 @@ void Map27::special() {
}
}
- desert();
+ if (_walls[g_maps->_mapOffset] == 0xff) {
+ desert();
+ } else {
+ g_maps->clearSpecial();
+ g_globals->_encounters.execute();
+ }
}
void Map27::special00() {
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
index 17620247638..85c0459c67e 100644
--- a/engines/mm/mm1/maps/map29.cpp
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -48,7 +48,7 @@ void Map29::special() {
}
}
- switch (_states[g_maps->_mapOffset]) {
+ switch (_walls[g_maps->_mapOffset]) {
case 0:
if (getRandomNumber(50) == 50) {
int id1 = getRandomNumber(16);
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index 73985cea249..c8cd6218d14 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -49,7 +49,7 @@ void Map30::special() {
}
}
- if (_states[g_maps->_mapOffset] != 0xff) {
+ if (_walls[g_maps->_mapOffset] != 0xff) {
g_maps->clearSpecial();
int monsterCount = getRandomNumber(8) + 6;
int idx = getRandomNumber(8) - 1;
diff --git a/engines/mm/mm1/maps/map31.cpp b/engines/mm/mm1/maps/map31.cpp
index 0412da83f85..fd3c2add92d 100644
--- a/engines/mm/mm1/maps/map31.cpp
+++ b/engines/mm/mm1/maps/map31.cpp
@@ -47,7 +47,7 @@ void Map31::special() {
}
- if (_states[g_maps->_mapOffset] != 0xff) {
+ if (_walls[g_maps->_mapOffset] != 0xff) {
if (getRandomNumber(100) < 25) {
g_maps->clearSpecial();
g_globals->_encounters.execute();
diff --git a/engines/mm/mm1/maps/map32.cpp b/engines/mm/mm1/maps/map32.cpp
index 03fd6a0c695..e80021f1eca 100644
--- a/engines/mm/mm1/maps/map32.cpp
+++ b/engines/mm/mm1/maps/map32.cpp
@@ -48,7 +48,7 @@ void Map32::special() {
}
}
- if (_states[g_maps->_mapOffset] == 0x55 && g_maps->_mapPos.x < 13) {
+ if (_walls[g_maps->_mapOffset] == 0x55 && g_maps->_mapPos.x < 13) {
send(SoundMessage(STRING["maps.map32.music"]));
} else {
g_maps->clearSpecial();
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index 2b96ea7d8e6..4c8bfcf2a92 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -62,7 +62,7 @@ void Map33::special() {
}
}
- if (_states[g_maps->_mapOffset] == 0xff) {
+ if (_walls[g_maps->_mapOffset] == 0xff) {
if (g_maps->_mapPos.x >= 6 || g_maps->_mapPos.y < 5 ||
g_maps->_mapPos.y >= 8) {
if (g_maps->_mapPos.y < 5 && g_maps->_forwardMask != DIRMASK_N) {
diff --git a/engines/mm/mm1/maps/map52.cpp b/engines/mm/mm1/maps/map52.cpp
index 99edcc85c10..14afbadaa83 100644
--- a/engines/mm/mm1/maps/map52.cpp
+++ b/engines/mm/mm1/maps/map52.cpp
@@ -54,7 +54,7 @@ void Map52::special00() {
}
void Map52::special01() {
- _walls[0x18] |= 0x80;
+ _states[0x18] |= 0x80;
g_maps->_mapPos = Common::Point(8, 1);
updateGame();
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
index 920a43ad34b..1ecf8795250 100644
--- a/engines/mm/mm1/views/maps/access_code.cpp
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -68,11 +68,11 @@ void AccessCode::correctCode() {
map[VAL1] = 0;
for (int i = 0; i < 8; ++i)
- map._walls[OFFSETS1[i]] ^= 4;
+ map._states[OFFSETS1[i]] ^= 4;
for (int i = 0; i < 8; ++i)
- map._walls[OFFSETS2[i]] ^= 0x40;
- map._walls[119] ^= 0x10;
- map._walls[120] ^= 1;
+ map._states[OFFSETS2[i]] ^= 0x40;
+ map._states[119] ^= 0x10;
+ map._states[120] ^= 1;
}
void AccessCode::incorrectCode() {
Commit: 9af8ddddb60b612994bf5cf5693c7a306df4937e
https://github.com/scummvm/scummvm/commit/9af8ddddb60b612994bf5cf5693c7a306df4937e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: In progress trap damage view
Changed paths:
A engines/mm/mm1/data/trap.cpp
A engines/mm/mm1/data/trap.h
A engines/mm/mm1/views/trap.cpp
A engines/mm/mm1/views/trap.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/unlock.cpp
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 42b977b8830..650e7005a61 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -248,6 +248,19 @@
congrats: "CONGRATULATIONS! YOU ARE NOW LEVEL "
hp: "YOU GAINED %d HIT POINTS"
new_spells: "YOU GAINED NEW SPELLS!"
+ trap:
+ oops: "OOPS A TRAP!"
+ 0: "DARTS!! A SWARM OF POISONOUS DARTS\n FILL THE AIR!"
+ 1: "SPIKES!! DEADLY SPIKES SPRING FORTH!"
+ 2: "ARROWS!! A SUDDEN ONSLAUGHT OF POISONOUS ARROWS PERMEATE THE PARTY!"
+ 3: "BLADES!! RAZOR SHARP BLADES SLICE\n THROUGH THE PARTY!"
+ 4: "BOILING OIL!! STREAMS OF BOILING OIL\n COVER THE PARTY!"
+ 5: "GAS!! A FAINT HISS CAN BE HEARD AS\n NOXIOUS FUMES FILL THE AIR!"
+ 6: "FIREBALL!! A FIERY EXPLOSION ENGULFS\n THE AREA!"
+ 7: "LIGHTNING BOLT!! ELECTRIC CURRENTS\n SINGE THE PARTY!"
+ 8: "ACID!! A FINE MIST OF VOLATILE ACID\n SPRAYS THE PARTY!"
+ 9: "ICE STORM!! PARTICLES OF SPLINTERED ICE\n HAIL THROUGH THE AIR!"
+ 10: "DEATH RAY!! A BLINDING LIGHT SEARS\n THROUGH THE PARTY!"
unlock:
who_will_try: "WHO WILL TRY '1'-'%c'?"
success: "SUCCESS!"
diff --git a/engines/mm/mm1/data/trap.cpp b/engines/mm/mm1/data/trap.cpp
new file mode 100644
index 00000000000..cc13087211a
--- /dev/null
+++ b/engines/mm/mm1/data/trap.cpp
@@ -0,0 +1,97 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/data/trap.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+
+byte TrapData::ARRAY1[11] = {
+ 0, 0, 0, 0, 0, 0, 91, 95, 97, 93, 89
+};
+byte TrapData::ARRAY2[11] = {
+ 16, 32, 16, 16, 2, 1, 2, 32, 2, 2, 2
+};
+byte TrapData::ARRAY3[11] = {
+ 16, 16, 16, 32, 2, 16, 64, 64, 2, 32, 32
+};
+byte TrapData::ARRAY4[11] = {
+ 64, 64, 64, 64, 64, 192, 192, 192, 255, 64, 224
+};
+byte TrapData::DAMAGE_TYPE[7] = {
+ 3, 0, 2, 5, 4, 1, 6
+};
+
+
+void TrapData::trap() {
+ _trapType = getRandomNumber(11) - 1;
+
+ int maxVal = 4;
+ for (int i = (int)g_globals->_treasure._container - 1; i > 0; i -= 2) {
+ maxVal <<= 1;
+ }
+ maxVal += getRandomNumber(maxVal);
+
+ _value3 = ARRAY1[_trapType];
+
+ int val2;
+ if (g_globals->_treasure._container < WOODEN_BOX)
+ val2 = 0;
+ else if (g_globals->_treasure._container < SILVER_BOX)
+ val2 = ARRAY2[_trapType];
+ else if (g_globals->_treasure._container < BLACK_BOX)
+ val2 = ARRAY3[_trapType];
+ else
+ val2 = ARRAY4[_trapType];
+
+ int idx = _trapType;
+ if (idx >= 7)
+ idx -= 5;
+ else if (val2 == 16)
+ idx = 0;
+ else if (val2 == 32)
+ idx = 1;
+ else
+ idx = -1;
+
+ int val4 = 0;
+ _value2 = 0;
+ if (idx >= 0) {
+ int spellCount = g_globals->_activeSpells._arr[DAMAGE_TYPE[idx]];
+ if (spellCount > 0 && getRandomNumber(100) < spellCount) {
+ _value2 = val4 = 1;
+ maxVal = 1;
+ }
+ }
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i, _value2 = val4) {
+ _value1 = maxVal;
+ damageChar(i);
+ }
+}
+
+void TrapData::damageChar(uint partyIndex) {
+
+}
+
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/data/trap.h b/engines/mm/mm1/data/trap.h
new file mode 100644
index 00000000000..6b26108f0bb
--- /dev/null
+++ b/engines/mm/mm1/data/trap.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_DATA_TRAP_H
+#define MM1_DATA_TRAP_H
+
+#include "common/scummsys.h"
+#include "mm/mm1/game/game_logic.h"
+
+namespace MM {
+namespace MM1 {
+
+class TrapData : public Game::GameLogic {
+private:
+ /**
+ * Damages a party member from the trap
+ */
+ void damageChar(uint partyIndex);
+
+protected:
+ static byte ARRAY1[11];
+ static byte ARRAY2[11];
+ static byte ARRAY3[11];
+ static byte ARRAY4[11];
+ static byte DAMAGE_TYPE[7];
+
+ int _trapType = 0;
+ int _value1 = 0;
+ int _value2 = 0;
+ int _value3 = 0;
+
+ virtual void trap();
+};
+
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index bfed2c216f0..0eb72f451ce 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -81,7 +81,7 @@ enum DataOffset {
MAP_FLAGS = 46,
MAP_47 = 47,
MAP_DARTS_THRESHOLD = 48,
- MAP_UNLOCK_THRESHOLD = 49
+ MAP_49 = 49
};
enum WallType {
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 4a3204560b9..bf87f6a842b 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -37,6 +37,7 @@
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/rest.h"
#include "mm/mm1/views/search.h"
+#include "mm/mm1/views/trap.h"
#include "mm/mm1/views/unlock.h"
#include "mm/mm1/views/locations/blacksmith.h"
#include "mm/mm1/views/locations/inn.h"
@@ -91,6 +92,7 @@ private:
Views::Rest _rest;
Views::Search _search;
Views::Title _title;
+ Views::Trap _trap;
Views::Unlock _unlock;
Views::CharacterInfo _characterInfo;
diff --git a/engines/mm/mm1/views/trap.cpp b/engines/mm/mm1/views/trap.cpp
new file mode 100644
index 00000000000..5afc52dfca4
--- /dev/null
+++ b/engines/mm/mm1/views/trap.cpp
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/trap.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Trap::Trap() : TextView("Trap") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Trap::msgGame(const GameMessage &msg) {
+ if (msg._name == "TRIGGER") {
+ replaceView(this);
+ _mode = OOPS;
+ g_globals->_treasure._container =
+ g_maps->_currentMap->dataByte(Maps::MAP_49);
+ g_globals->_currCharacter = &g_globals->_party[0];
+
+ Sound::sound(SOUND_2);
+ return true;
+
+ } else if (msg._name == "TRAP") {
+ trap();
+ return true;
+
+ }
+
+ return false;
+}
+
+void Trap::draw() {
+ clearSurface();
+
+ switch (_mode) {
+ case OOPS:
+ writeString(9, 1, STRING["dialogs.trap.oops"]);
+ delaySeconds(3);
+ break;
+
+ case TRAP:
+ writeString(0, 1, STRING[
+ Common::String::format("dialogs.trap.%d", _trapType)
+ ]);
+ delaySeconds(8);
+ break;
+ }
+}
+
+bool Trap::msgKeypress(const KeypressMessage &msg) {
+ cancelDelay();
+ timeout();
+
+ return true;
+}
+
+void Trap::timeout() {
+ switch (_mode) {
+ case OOPS:
+ trap();
+ draw();
+ break;
+ case TRAP:
+ close();
+ break;
+ }
+}
+
+void Trap::trap() {
+ TrapData::trap();
+ _mode = TRAP;
+ draw();
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/trap.h b/engines/mm/mm1/views/trap.h
new file mode 100644
index 00000000000..02a00c375f6
--- /dev/null
+++ b/engines/mm/mm1/views/trap.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_TRAP_H
+#define MM1_VIEWS_TRAP_H
+
+#include "mm/mm1/views/text_view.h"
+#include "mm/mm1/data/trap.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Trap : public TextView, public TrapData {
+private:
+ enum Mode { OOPS, TRAP };
+ Mode _mode = OOPS;
+
+protected:
+ void trap() override;
+
+public:
+ Trap();
+ virtual ~Trap() {}
+
+ bool msgGame(const GameMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ void timeout() override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/unlock.cpp b/engines/mm/mm1/views/unlock.cpp
index 23a8742dfc9..afcdff42f79 100644
--- a/engines/mm/mm1/views/unlock.cpp
+++ b/engines/mm/mm1/views/unlock.cpp
@@ -104,7 +104,7 @@ void Unlock::charSelected(uint charIndex) {
if (isFocused())
close();
- int val = g_maps->_currentMap->dataByte(Maps::MAP_UNLOCK_THRESHOLD) * 4 +
+ int val = g_maps->_currentMap->dataByte(Maps::MAP_49) * 4 +
getRandomNumber(100);
if (val < c._v6c) {
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 1905314dc50..c6babfca614 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -23,6 +23,7 @@ MODULE_OBJS := \
mm1/data/party.o \
mm1/data/roster.o \
mm1/data/text_parser.o \
+ mm1/data/trap.o \
mm1/data/treasure.o \
mm1/game/game_logic.o \
mm1/game/combat.o \
@@ -104,6 +105,7 @@ MODULE_OBJS := \
mm1/views/title.o \
mm1/views/text_entry.o \
mm1/views/text_view.o \
+ mm1/views/trap.o \
mm1/views/unlock.o \
mm1/views_enh/button_container.o \
mm1/views_enh/character_info.o \
Commit: 162e443890e93f968a7162f5a436a41e771dd8b3
https://github.com/scummvm/scummvm/commit/162e443890e93f968a7162f5a436a41e771dd8b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:31+01:00
Commit Message:
MM: MM1: Remainder of trap logic
Changed paths:
engines/mm/mm1/data/trap.cpp
engines/mm/mm1/data/trap.h
diff --git a/engines/mm/mm1/data/trap.cpp b/engines/mm/mm1/data/trap.cpp
index cc13087211a..61de8d36aa1 100644
--- a/engines/mm/mm1/data/trap.cpp
+++ b/engines/mm/mm1/data/trap.cpp
@@ -25,16 +25,21 @@
namespace MM {
namespace MM1 {
-byte TrapData::ARRAY1[11] = {
- 0, 0, 0, 0, 0, 0, 91, 95, 97, 93, 89
+int8 TrapData::RESISTANCE_INDEXES[11] = {
+ -1, -1, -1, -1, -1, -1,
+ 1, // Fire
+ 3, // Electricity
+ 4, // Acid
+ 2, // Cold
+ 0 // Magic
};
-byte TrapData::ARRAY2[11] = {
+byte TrapData::CONDITIONS1[11] = {
16, 32, 16, 16, 2, 1, 2, 32, 2, 2, 2
};
-byte TrapData::ARRAY3[11] = {
+byte TrapData::CONDITIONS2[11] = {
16, 16, 16, 32, 2, 16, 64, 64, 2, 32, 32
};
-byte TrapData::ARRAY4[11] = {
+byte TrapData::CONDITIONS3[11] = {
64, 64, 64, 64, 64, 192, 192, 192, 255, 64, 224
};
byte TrapData::DAMAGE_TYPE[7] = {
@@ -51,46 +56,85 @@ void TrapData::trap() {
}
maxVal += getRandomNumber(maxVal);
- _value3 = ARRAY1[_trapType];
+ _resistanceIndex = RESISTANCE_INDEXES[_trapType];
- int val2;
if (g_globals->_treasure._container < WOODEN_BOX)
- val2 = 0;
+ _condition = 0;
else if (g_globals->_treasure._container < SILVER_BOX)
- val2 = ARRAY2[_trapType];
+ _condition = CONDITIONS1[_trapType];
else if (g_globals->_treasure._container < BLACK_BOX)
- val2 = ARRAY3[_trapType];
+ _condition = CONDITIONS2[_trapType];
else
- val2 = ARRAY4[_trapType];
+ _condition = CONDITIONS3[_trapType];
int idx = _trapType;
if (idx >= 7)
idx -= 5;
- else if (val2 == 16)
+ else if (_condition == POISONED)
idx = 0;
- else if (val2 == 32)
+ else if (_condition == PARALYZED)
idx = 1;
else
idx = -1;
int val4 = 0;
- _value2 = 0;
+ _reduced = 0;
if (idx >= 0) {
int spellCount = g_globals->_activeSpells._arr[DAMAGE_TYPE[idx]];
if (spellCount > 0 && getRandomNumber(100) < spellCount) {
- _value2 = val4 = 1;
+ _reduced = val4 = 1;
maxVal = 1;
}
}
- for (uint i = 0; i < g_globals->_party.size(); ++i, _value2 = val4) {
- _value1 = maxVal;
+ for (uint i = 0; i < g_globals->_party.size(); ++i, _reduced = val4) {
+ _hp = maxVal;
damageChar(i);
}
}
void TrapData::damageChar(uint partyIndex) {
+ Character &c = g_globals->_party[partyIndex];
+ if (&c != g_globals->_currCharacter)
+ _hp >>= 1;
+ if (_resistanceIndex != -1 &&
+ c._resistances._arr[_resistanceIndex] != 0 &&
+ getRandomNumber(100) < c._resistances._arr[_resistanceIndex]) {
+ _hp >>= 1;
+ ++_reduced;
+ }
+
+ int luckLevel1 = c._luck + c._level;
+ int luckLevel2 = getRandomNumber(luckLevel1 + 20);
+
+ if (getRandomNumber(luckLevel2) < luckLevel1) {
+ _hp >>= 1;
+ ++_reduced;
+ }
+
+ if (c._condition & BAD_CONDITION) {
+ c._hpBase = 0;
+
+ } else if (c._condition & UNCONSCIOUS) {
+ c._condition = BAD_CONDITION | DEAD;
+ c._hpBase = 0;
+
+ } else {
+ c._hpBase = MAX((int)c._hpBase - _hp, 0);
+
+ if (c._hpBase == 0) {
+ c._condition |= UNCONSCIOUS;
+
+ } else if (!_reduced && _condition &&
+ getRandomNumber(luckLevel1 + 20) >= luckLevel1) {
+ if (_condition >= UNCONSCIOUS)
+ c._hpBase = 0;
+
+ if (!(c._condition & BAD_CONDITION))
+ c._condition = _condition;
+ }
+ }
}
} // namespace MM1
diff --git a/engines/mm/mm1/data/trap.h b/engines/mm/mm1/data/trap.h
index 6b26108f0bb..160f43bd644 100644
--- a/engines/mm/mm1/data/trap.h
+++ b/engines/mm/mm1/data/trap.h
@@ -36,16 +36,17 @@ private:
void damageChar(uint partyIndex);
protected:
- static byte ARRAY1[11];
- static byte ARRAY2[11];
- static byte ARRAY3[11];
- static byte ARRAY4[11];
+ static int8 RESISTANCE_INDEXES[11];
+ static byte CONDITIONS1[11];
+ static byte CONDITIONS2[11];
+ static byte CONDITIONS3[11];
static byte DAMAGE_TYPE[7];
int _trapType = 0;
- int _value1 = 0;
- int _value2 = 0;
- int _value3 = 0;
+ int _hp = 0;
+ int _reduced = 0;
+ int _resistanceIndex = 0;
+ byte _condition = 0;
virtual void trap();
};
Commit: 9ad34f448606743e28e05d931df0b04513161a0e
https://github.com/scummvm/scummvm/commit/9ad34f448606743e28e05d931df0b04513161a0e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Hook up Unlock to call Trap when trap triggered
Changed paths:
engines/mm/mm1/views/trap.cpp
engines/mm/mm1/views/unlock.cpp
engines/mm/mm1/views/unlock.h
diff --git a/engines/mm/mm1/views/trap.cpp b/engines/mm/mm1/views/trap.cpp
index 5afc52dfca4..c92e956da9e 100644
--- a/engines/mm/mm1/views/trap.cpp
+++ b/engines/mm/mm1/views/trap.cpp
@@ -43,9 +43,9 @@ bool Trap::msgGame(const GameMessage &msg) {
return true;
} else if (msg._name == "TRAP") {
+ replaceView(this);
trap();
return true;
-
}
return false;
diff --git a/engines/mm/mm1/views/unlock.cpp b/engines/mm/mm1/views/unlock.cpp
index afcdff42f79..fb01963fcbd 100644
--- a/engines/mm/mm1/views/unlock.cpp
+++ b/engines/mm/mm1/views/unlock.cpp
@@ -108,10 +108,7 @@ void Unlock::charSelected(uint charIndex) {
getRandomNumber(100);
if (val < c._v6c) {
- g_maps->_currentState =
- g_maps->_currentMap->_states[g_maps->_mapOffset] ^=
- g_maps->_forwardMask & 0x55;
-
+ unlockDoor();
send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
} else if (getRandomNumber(100) <
@@ -119,15 +116,18 @@ void Unlock::charSelected(uint charIndex) {
send(InfoMessage(8, 1, STRING["dialogs.unlock.failed"]));
} else {
- g_maps->_currentState =
- g_maps->_currentMap->_states[g_maps->_mapOffset] ^=
- g_maps->_forwardMask & 0x55;
- // TODO
- warning("TODO: Darts triggered");
+ unlockDoor();
+ send("Trap", GameMessage("TRIGGER"));
}
}
}
+void Unlock::unlockDoor() {
+ g_maps->_currentState =
+ g_maps->_currentMap->_states[g_maps->_mapOffset] ^=
+ g_maps->_forwardMask & 0x55;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/unlock.h b/engines/mm/mm1/views/unlock.h
index b02e956b4fe..009239038c8 100644
--- a/engines/mm/mm1/views/unlock.h
+++ b/engines/mm/mm1/views/unlock.h
@@ -31,6 +31,7 @@ namespace Views {
class Unlock : public TextView {
private:
void charSelected(uint charIndex);
+ void unlockDoor();
public:
Unlock();
virtual ~Unlock() {}
Commit: e20bff29a0aaa090d4d49c67c5bc93c1e28b7a57
https://github.com/scummvm/scummvm/commit/e20bff29a0aaa090d4d49c67c5bc93c1e28b7a57
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Fixes for trap triggered display
Changed paths:
engines/mm/mm1/views/trap.cpp
engines/mm/mm1/views/trap.h
diff --git a/engines/mm/mm1/views/trap.cpp b/engines/mm/mm1/views/trap.cpp
index c92e956da9e..4f995b29d79 100644
--- a/engines/mm/mm1/views/trap.cpp
+++ b/engines/mm/mm1/views/trap.cpp
@@ -33,8 +33,7 @@ Trap::Trap() : TextView("Trap") {
bool Trap::msgGame(const GameMessage &msg) {
if (msg._name == "TRIGGER") {
- replaceView(this);
- _mode = OOPS;
+ open();
g_globals->_treasure._container =
g_maps->_currentMap->dataByte(Maps::MAP_49);
g_globals->_currCharacter = &g_globals->_party[0];
@@ -43,7 +42,6 @@ bool Trap::msgGame(const GameMessage &msg) {
return true;
} else if (msg._name == "TRAP") {
- replaceView(this);
trap();
return true;
}
@@ -54,19 +52,8 @@ bool Trap::msgGame(const GameMessage &msg) {
void Trap::draw() {
clearSurface();
- switch (_mode) {
- case OOPS:
- writeString(9, 1, STRING["dialogs.trap.oops"]);
- delaySeconds(3);
- break;
-
- case TRAP:
- writeString(0, 1, STRING[
- Common::String::format("dialogs.trap.%d", _trapType)
- ]);
- delaySeconds(8);
- break;
- }
+ writeString(9, 1, STRING["dialogs.trap.oops"]);
+ delaySeconds(3);
}
bool Trap::msgKeypress(const KeypressMessage &msg) {
@@ -77,21 +64,16 @@ bool Trap::msgKeypress(const KeypressMessage &msg) {
}
void Trap::timeout() {
- switch (_mode) {
- case OOPS:
- trap();
- draw();
- break;
- case TRAP:
+ if (isFocused())
close();
- break;
- }
+ trap();
}
void Trap::trap() {
TrapData::trap();
- _mode = TRAP;
- draw();
+
+ send(InfoMessage(0, 1,
+ STRING[Common::String::format("dialogs.trap.%d", _trapType)]));
}
} // namespace Views
diff --git a/engines/mm/mm1/views/trap.h b/engines/mm/mm1/views/trap.h
index 02a00c375f6..d4268166d90 100644
--- a/engines/mm/mm1/views/trap.h
+++ b/engines/mm/mm1/views/trap.h
@@ -30,10 +30,6 @@ namespace MM1 {
namespace Views {
class Trap : public TextView, public TrapData {
-private:
- enum Mode { OOPS, TRAP };
- Mode _mode = OOPS;
-
protected:
void trap() override;
Commit: 55f17ed0391eb6b4ce709d15815956f48b2c5491
https://github.com/scummvm/scummvm/commit/55f17ed0391eb6b4ce709d15815956f48b2c5491
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Give time to ready info messages when party dead
When an action kills off the party, instead of requiring
dead checks everywhere, now the game message display
will automatically wait for a keypress when the party
is dead, and then directly switch to the death screen
Changed paths:
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/views/game_messages.cpp
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 1f308cd77f1..e9a57503a52 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -102,18 +102,27 @@ bool Party::hasItem(byte itemId) const {
return false;
}
-bool Party::checkPartyDead() const {
+bool Party::isPartyDead() const {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- if (!(c._condition & (ASLEEP | STONE | DEAD | BAD_CONDITION)))
+ if (!(c._condition & (ASLEEP | PARALYZED | UNCONSCIOUS | BAD_CONDITION)))
return false;
}
- // At this point, there's no good characters.
- // So redirect to the death screen
- g_events->replaceView("Dead");
return true;
}
+bool Party::checkPartyDead() const {
+ if (isPartyDead()) {
+ // At this point, there's no good characters.
+ // So redirect to the death screen
+ g_events->clearViews();
+ g_events->addView("Dead");
+ return true;
+ } else {
+ return false;
+ }
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index ea68c15baa4..b46f6fff54f 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -71,6 +71,11 @@ struct Party : public Common::Array<Character> {
*/
bool hasItem(byte itemId) const;
+ /**
+ * Returns true if the party is dead or out of action
+ */
+ bool isPartyDead() const;
+
/**
* Checks whether the party is dead or out of action,
* and if so, switches to the death screen
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 1ac3d40154d..4ee28faa345 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -52,7 +52,8 @@ void GameMessages::draw() {
}
bool GameMessages::msgInfo(const InfoMessage &msg) {
- if (msg._ynCallback || msg._keyCallback) {
+ if (msg._ynCallback || msg._keyCallback ||
+ g_globals->_party.isPartyDead()) {
// Do a first draw to show 3d view at new position
g_events->redraw();
g_events->drawElements();
@@ -81,7 +82,13 @@ bool GameMessages::msgInfo(const InfoMessage &msg) {
}
bool GameMessages::msgKeypress(const KeypressMessage &msg) {
- if (g_events->focusedView() == this && !isDelayActive()) {
+ if (g_globals->_party.isPartyDead()) {
+ // Party is dead, so now that players have read whatever
+ // message was displayed, switch to the Dead screen
+ g_events->clearViews();
+ addView("Dead");
+
+ } else if (g_events->focusedView() == this && !isDelayActive()) {
if (_keyCallback) {
_keyCallback(msg);
} else if (msg.keycode == Common::KEYCODE_n) {
Commit: 3492b7ab100a6ab70b67bac6b7e32677265007e0
https://github.com/scummvm/scummvm/commit/3492b7ab100a6ab70b67bac6b7e32677265007e0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Add Dead view
Changed paths:
A engines/mm/mm1/views/dead.cpp
A engines/mm/mm1/views/dead.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/sound.cpp
engines/mm/mm1/sound.h
engines/mm/mm1/views/dialogs.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 650e7005a61..92ecd080f94 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -82,6 +82,13 @@
reroll: "'ENT' TO RE-ROLL"
start_over: "'ESC' START OVER"
name: "NAME:"
+ dead:
+ 1: "THE SHADOW OF DEATH"
+ 2: "HAS FALLEN UPON YOUR PARTY!"
+ 3: "FORTUNATELY, YOU MAY RENEW"
+ 4: "YOUR QUEST FROM THE LAST"
+ 5: "INN IN WHICH YOU STAYED"
+ 6: "BY PRESSING 'ENTER'"
inn:
title: "(%c) INN OF "
to_view: "TO VIEW"
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index e9ddd7116a6..152ada34d43 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -103,9 +103,12 @@ void Events::processEvent(Common::Event &ev) {
}
}
-void Events::replaceView(UIElement *ui) {
+void Events::replaceView(UIElement *ui, bool replaceAllViews) {
assert(ui);
- if (!_views.empty()) {
+ if (replaceAllViews) {
+ clearViews();
+
+ } else if (!_views.empty()) {
focusedView()->msgUnfocus(UnfocusMessage());
_views.pop();
}
@@ -115,7 +118,7 @@ void Events::replaceView(UIElement *ui) {
ui->msgFocus(FocusMessage());
}
-void Events::replaceView(const Common::String &name) {
+void Events::replaceView(const Common::String &name, bool replaceAllViews) {
replaceView(findView(name));
}
@@ -273,12 +276,12 @@ UIElement *UIElement::findView(const Common::String &name) {
return nullptr;
}
-void UIElement::replaceView(UIElement *ui) {
- g_events->replaceView(ui);
+void UIElement::replaceView(UIElement *ui, bool replaceAllViews) {
+ g_events->replaceView(ui, replaceAllViews);
}
-void UIElement::replaceView(const Common::String &name) {
- g_events->replaceView(name);
+void UIElement::replaceView(const Common::String &name, bool replaceAllViews) {
+ g_events->replaceView(name, replaceAllViews);
}
void UIElement::addView(UIElement *ui) {
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 0dfdaed4339..9febbd56715 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -154,8 +154,8 @@ public:
/**
* Sets the focus to a new view
*/
- void replaceView(UIElement *ui);
- void replaceView(const Common::String &name);
+ void replaceView(UIElement *ui, bool replaceAllViews = false);
+ void replaceView(const Common::String &name, bool replaceAllViews = false);
/**
* Adds a focused view to the view stack without replacing current one
@@ -286,8 +286,8 @@ public:
/**
* Sets the focus to a new view
*/
- void replaceView(UIElement *ui);
- void replaceView(const Common::String &name);
+ void replaceView(UIElement *ui, bool replaceAllViews = false);
+ void replaceView(const Common::String &name, bool replaceAllViews = false);
/**
* Adds a focused view to the view stack without replacing current one
diff --git a/engines/mm/mm1/sound.cpp b/engines/mm/mm1/sound.cpp
index 4383e5a4cf9..0b6387a8611 100644
--- a/engines/mm/mm1/sound.cpp
+++ b/engines/mm/mm1/sound.cpp
@@ -33,5 +33,9 @@ void Sound::sound2(SoundId soundNum) {
warning("TODO: sound2 %d", (int)soundNum);
}
+void Sound::stopSound() {
+ warning("TODO: stopSound");
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
index c6b11a90abf..7873f936e7c 100644
--- a/engines/mm/mm1/sound.h
+++ b/engines/mm/mm1/sound.h
@@ -25,12 +25,15 @@
namespace MM {
namespace MM1 {
-enum SoundId { SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3, SOUND_8 = 8 };
+enum SoundId {
+ SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3, SOUND_4 = 4, SOUND_8 = 8
+};
class Sound {
public:
static void sound(SoundId soundNum);
static void sound2(SoundId soundNum);
+ static void stopSound();
};
} // namespace MM1
diff --git a/engines/mm/mm1/views/dead.cpp b/engines/mm/mm1/views/dead.cpp
new file mode 100644
index 00000000000..bc031a4627d
--- /dev/null
+++ b/engines/mm/mm1/views/dead.cpp
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/dead.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+bool Dead::msgFocus(const FocusMessage &msg) {
+ TextView::msgFocus(msg);
+ Sound::sound2(SOUND_4);
+
+ g_globals->_party.clear();
+ g_globals->_roster.load();
+ g_globals->_activeSpells.clear();
+
+ return true;
+}
+
+void Dead::draw() {
+ clearSurface();
+ writeLine(4);
+ writeString(6, 10, STRING["dialogs.dead.1"]);
+ writeString(7, 8, STRING["dialogs.dead.2"]);
+ writeString(7, 10, STRING["dialogs.dead.3"]);
+ writeString(8, 12, STRING["dialogs.dead.4"]);
+ writeString(8, 14, STRING["dialogs.dead.5"]);
+ writeString(10, 16, STRING["dialogs.dead.6"]);
+ writeLine(18);
+}
+
+void Dead::writeLine(int y) {
+ _textPos = Common::Point(0, y);
+
+ for (int i = 0; i < 40; ++i)
+ writeChar(i == 0 || i == 39 ? '+' : '-');
+}
+
+bool Dead::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_RETURN) {
+ replaceView("MainMenu");
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/dead.h b/engines/mm/mm1/views/dead.h
new file mode 100644
index 00000000000..f4cc028af98
--- /dev/null
+++ b/engines/mm/mm1/views/dead.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_DEAD_H
+#define MM1_VIEWS_DEAD_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Dead : public TextView {
+private:
+ /**
+ * Writes a horizontal text line
+ */
+ void writeLine(int y);
+public:
+ Dead() : TextView("Dead") {}
+ virtual ~Dead() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index bf87f6a842b..ce17a001592 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -26,6 +26,7 @@
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/combat.h"
#include "mm/mm1/views/create_characters.h"
+#include "mm/mm1/views/dead.h"
#include "mm/mm1/views/encounter.h"
#include "mm/mm1/views/game.h"
#include "mm/mm1/views/main_menu.h"
@@ -83,6 +84,7 @@ private:
Views::AreYouReady _areYouReady;
Views::Combat _combat;
Views::CreateCharacters _createCharacters;
+ Views::Dead _dead;
Views::Encounter _encounter;
Views::Game _game;
Views::MainMenu _mainMenu;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c6babfca614..ed8fe0571a3 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -90,6 +90,7 @@ MODULE_OBJS := \
mm1/views/characters.o \
mm1/views/combat.o \
mm1/views/create_characters.o \
+ mm1/views/dead.o \
mm1/views/encounter.o \
mm1/views/game.o \
mm1/views/game_commands.o \
Commit: 8c7db228f67ddbc3df49c2f35b46b70a55d1dea6
https://github.com/scummvm/scummvm/commit/8c7db228f67ddbc3df49c2f35b46b70a55d1dea6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Implement bash view
Changed paths:
A engines/mm/mm1/views/bash.cpp
A engines/mm/mm1/views/bash.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/unlock.cpp
engines/mm/mm1/views/unlock.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 4aa495ce4cd..f51cee39429 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -89,9 +89,6 @@ bool ViewBase::msgAction(const ActionMessage &msg) {
case KEYBIND_TURN_RIGHT:
turnRight();
break;
- case KEYBIND_BASH:
- bash();
- break;
default:
return TextView::msgAction(msg);
}
@@ -243,50 +240,6 @@ void ViewBase::barrier() {
Sound::sound(SOUND_1);
}
-void ViewBase::bash() {
- Maps::Maps &maps = g_globals->_maps;
- Maps::Map &map = *maps._currentMap;
-
- if (!(maps._currentState & 0x55 & maps._forwardMask) ||
- !(maps._currentWalls & maps._forwardMask)) {
- // No forward obstruction, so simply move forward
- forward(KEYBIND_FORWARDS);
- } else {
- int index = Maps::MAP_32;
- if (!(maps._currentWalls & maps._forwardMask & 0x55))
- index = Maps::MAP_31;
- else if (!(maps._currentWalls & maps._forwardMask & 0x55))
- index = Maps::MAP_30;
-
- if (map.dataByte(index) != 1) {
- forward(KEYBIND_FORWARDS);
- } else {
- Sound::sound(SOUND_1);
-
- uint might = g_engine->getRandomNumber(100);
- for (uint i = 0; i < g_globals->_party.size(); ++i)
- might += g_globals->_party[i]._might;
- might = MIN(might, 255U);
-
- // Check for busting
- uint threshold = map[Maps::MAP_45];
- if (threshold && might >= threshold) {
- map._states[maps._mapOffset + maps._forwardMask] ^=
- (maps._forwardMask & 0x55);
- maps._currentState = map._states[maps._mapOffset + maps._forwardMask];
- }
-
- // Check for trap being triggered
- if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DARTS_THRESHOLD]) {
- warning("TODO: trigger trap");
-
- } else {
- forward(KEYBIND_FORWARDS);
- }
- }
- }
-}
-
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index 33438f0393a..fd8f5ae5bf9 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -70,10 +70,6 @@ private:
*/
void barrier();
- /**
- * Bash
- */
- void bash();
public:
ViewBase(UIElement *owner);
virtual ~ViewBase() {}
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 1f803c8d7f0..2aac83bfe04 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -117,6 +117,11 @@ void Map::encounter(const byte *id1, const byte *id2) {
enc.execute();
}
+void Map::unlockDoor() {
+ g_maps->_currentState = _states[g_maps->_mapOffset] ^=
+ g_maps->_forwardMask & 0x55;
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 0eb72f451ce..d40e54a6381 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -80,7 +80,7 @@ enum DataOffset {
MAP_45 = 45,
MAP_FLAGS = 46,
MAP_47 = 47,
- MAP_DARTS_THRESHOLD = 48,
+ MAP_TRAP_THRESHOLD = 48,
MAP_49 = 49
};
@@ -200,6 +200,11 @@ public:
* Redraw the game display
*/
static void redrawGame();
+
+ /**
+ * Unlocks door
+ */
+ void unlockDoor();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/bash.cpp b/engines/mm/mm1/views/bash.cpp
new file mode 100644
index 00000000000..c693f5f98f2
--- /dev/null
+++ b/engines/mm/mm1/views/bash.cpp
@@ -0,0 +1,89 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/bash.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+Bash::Bash() : TextView("Bash") {
+}
+
+bool Bash::msgGame(const GameMessage &msg) {
+ if (msg._name == "SHOW") {
+ bashDoor();
+ return true;
+ }
+
+ return false;
+}
+
+void Bash::bashDoor() {
+ byte walls = g_maps->_currentWalls & g_maps->_forwardMask;
+ if (!(g_maps->_currentState & 0x55 & g_maps->_forwardMask) || !walls) {
+ forwards();
+ return;
+ }
+
+ int val;
+ if (!(walls & 0x55))
+ val = 1;
+ else if (!(g_maps->_currentWalls & g_maps->_currentWalls & 0xaa))
+ val = 0;
+ else
+ val = 2;
+
+ if (g_maps->_currentMap->dataByte(Maps::MAP_30 + val) != 1) {
+ forwards();
+ return;
+ }
+
+ Sound::sound(SOUND_1);
+ int might = getRandomNumber(100);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ might += c._might;
+ }
+
+ int threshold = g_maps->_currentMap->dataByte(Maps::MAP_45);
+
+ if (threshold && might >= threshold) {
+ g_maps->_currentMap->unlockDoor();
+ }
+
+ if (getRandomNumber(100) >= g_maps->_currentMap->dataByte(Maps::MAP_TRAP_THRESHOLD)) {
+ send("Trap", GameMessage("TRIGGER"));
+ } else {
+ forwards();
+ }
+}
+
+void Bash::forwards() {
+ g_events->addAction(KEYBIND_FORWARDS);
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/bash.h b/engines/mm/mm1/views/bash.h
new file mode 100644
index 00000000000..3c5ebe9acf8
--- /dev/null
+++ b/engines/mm/mm1/views/bash.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_BASH_H
+#define MM1_VIEWS_BASH_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+class Bash : public TextView {
+private:
+ /**
+ * Handle bashing the door
+ */
+ void bashDoor();
+
+ /**
+ * When there's no door to bash, the bash action
+ * is transformed into a simple forwards movement
+ */
+ void forwards();
+public:
+ Bash();
+ virtual ~Bash() {}
+
+ /**
+ * Handles game messages
+ */
+ bool msgGame(const GameMessage &msg) override;
+
+ /**
+ * The view doesn't actually have any rendering,
+ * so the draw method has no implementation
+ */
+ void draw() override {}
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index ce17a001592..b723f53d12d 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -24,6 +24,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/are_you_ready.h"
+#include "mm/mm1/views/bash.h"
#include "mm/mm1/views/combat.h"
#include "mm/mm1/views/create_characters.h"
#include "mm/mm1/views/dead.h"
@@ -82,6 +83,7 @@ namespace Views {
struct Dialogs {
private:
Views::AreYouReady _areYouReady;
+ Views::Bash _bash;
Views::Combat _combat;
Views::CreateCharacters _createCharacters;
Views::Dead _dead;
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 88356e2a867..465b1393f08 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -48,8 +48,10 @@ void Game::draw() {
bool Game::msgAction(const ActionMessage &msg) {
switch (msg._action) {
+ case KEYBIND_BASH:
+ send("Bash", GameMessage("SHOW"));
+ break;
case KEYBIND_ORDER:
-// g_events->send("Game", GameMessage("ORDER"));
addView("Order");
return true;
case KEYBIND_PROTECT:
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 04c46ff1252..502c4c1b9b3 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -140,7 +140,7 @@ void Search::timeout() {
case INITIAL: {
Maps::Map &map = *g_maps->_currentMap;
_val1 = MIN(g_globals->_treasure._container * 8 +
- map[Maps::MAP_DARTS_THRESHOLD], 255);
+ map[Maps::MAP_TRAP_THRESHOLD], 255);
if (!g_globals->_treasure[1]) {
g_globals->_treasure[1] = (getRandomNumber(100) < _val1) ? 1 : 2;
diff --git a/engines/mm/mm1/views/unlock.cpp b/engines/mm/mm1/views/unlock.cpp
index fb01963fcbd..aa1987da97a 100644
--- a/engines/mm/mm1/views/unlock.cpp
+++ b/engines/mm/mm1/views/unlock.cpp
@@ -108,26 +108,20 @@ void Unlock::charSelected(uint charIndex) {
getRandomNumber(100);
if (val < c._v6c) {
- unlockDoor();
+ g_maps->_currentMap->unlockDoor();
send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
} else if (getRandomNumber(100) <
- g_maps->_currentMap->dataByte(Maps::MAP_DARTS_THRESHOLD)) {
+ g_maps->_currentMap->dataByte(Maps::MAP_TRAP_THRESHOLD)) {
send(InfoMessage(8, 1, STRING["dialogs.unlock.failed"]));
} else {
- unlockDoor();
+ g_maps->_currentMap->unlockDoor();
send("Trap", GameMessage("TRIGGER"));
}
}
}
-void Unlock::unlockDoor() {
- g_maps->_currentState =
- g_maps->_currentMap->_states[g_maps->_mapOffset] ^=
- g_maps->_forwardMask & 0x55;
-}
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/unlock.h b/engines/mm/mm1/views/unlock.h
index 009239038c8..41db9d33ed0 100644
--- a/engines/mm/mm1/views/unlock.h
+++ b/engines/mm/mm1/views/unlock.h
@@ -31,7 +31,7 @@ namespace Views {
class Unlock : public TextView {
private:
void charSelected(uint charIndex);
- void unlockDoor();
+
public:
Unlock();
virtual ~Unlock() {}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index ed8fe0571a3..b787945133e 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -84,6 +84,7 @@ MODULE_OBJS := \
mm1/views/spells/recharge_item.o \
mm1/views/spells/teleport.o \
mm1/views/are_you_ready.o \
+ mm1/views/bash.o \
mm1/views/character_base.o \
mm1/views/character_info.o \
mm1/views/character_manage.o \
Commit: fdc0914e73539380837713d6bfe4317b05fbd8d0
https://github.com/scummvm/scummvm/commit/fdc0914e73539380837713d6bfe4317b05fbd8d0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Immediately process addAction/addKeypress calls
Changed paths:
engines/mm/mm1/events.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 152ada34d43..f62d9d24d3b 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -154,24 +154,16 @@ void Events::clearViews() {
}
void Events::addKeypress(const Common::KeyCode kc) {
- Common::Event e;
- e.type = Common::EVENT_KEYDOWN;
- e.kbd.keycode = kc;
- e.kbd.ascii = kc <= 127 ? kc : 0;
- g_system->getEventManager()->pushEvent(e);
+ Common::KeyState ks;
+ ks.keycode = kc;
+ if (kc >= Common::KEYCODE_SPACE && kc <= Common::KEYCODE_TILDE)
+ ks.ascii = kc;
- e.type = Common::EVENT_KEYUP;
- g_system->getEventManager()->pushEvent(e);
+ focusedView()->msgKeypress(KeypressMessage(ks));
}
void Events::addAction(KeybindingAction action) {
- Common::Event e;
- e.type = Common::EVENT_CUSTOM_BACKEND_ACTION_START;
- e.customType = action;
- g_system->getEventManager()->pushEvent(e);
-
- e.type = Common::EVENT_CUSTOM_BACKEND_ACTION_END;
- g_system->getEventManager()->pushEvent(e);
+ focusedView()->msgAction(ActionMessage(action));
}
/*------------------------------------------------------------------------*/
Commit: 1b6238d5b514162f6dfad1dee368d7d73c7c215a
https://github.com/scummvm/scummvm/commit/1b6238d5b514162f6dfad1dee368d7d73c7c215a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Fix selecting characters from Quick Ref view
Changed paths:
engines/mm/mm1/views/quick_ref.cpp
engines/mm/mm1/views/quick_ref.h
diff --git a/engines/mm/mm1/views/quick_ref.cpp b/engines/mm/mm1/views/quick_ref.cpp
index c29f80a032a..0fa678cf432 100644
--- a/engines/mm/mm1/views/quick_ref.cpp
+++ b/engines/mm/mm1/views/quick_ref.cpp
@@ -26,6 +26,16 @@ namespace MM {
namespace MM1 {
namespace Views {
+bool QuickRef::msgFocus(const FocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_PARTY_MENUS);
+ return TextView::msgFocus(msg);
+}
+
+bool QuickRef::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return TextView::msgUnfocus(msg);
+}
+
void QuickRef::draw() {
clearSurface();
writeString(STRING["dialogs.quick_ref.title"]);
diff --git a/engines/mm/mm1/views/quick_ref.h b/engines/mm/mm1/views/quick_ref.h
index 03cdffec995..85d3519c85e 100644
--- a/engines/mm/mm1/views/quick_ref.h
+++ b/engines/mm/mm1/views/quick_ref.h
@@ -36,6 +36,8 @@ public:
QuickRef() : CharacterBase("QuickRef") {}
virtual ~QuickRef() {}
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
Commit: a868a699dc92aab9e577490ffcaec5cb01d26bad
https://github.com/scummvm/scummvm/commit/a868a699dc92aab9e577490ffcaec5cb01d26bad
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:32+01:00
Commit Message:
MM: MM1: Fix Giant unfocus handler
Changed paths:
engines/mm/mm1/views/maps/giant.cpp
diff --git a/engines/mm/mm1/views/maps/giant.cpp b/engines/mm/mm1/views/maps/giant.cpp
index fc074d9fd39..bad954c7f8c 100644
--- a/engines/mm/mm1/views/maps/giant.cpp
+++ b/engines/mm/mm1/views/maps/giant.cpp
@@ -40,7 +40,7 @@ bool Giant::msgFocus(const FocusMessage &msg) {
bool Giant::msgUnfocus(const UnfocusMessage &msg) {
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
- return msgUnfocus(msg);
+ return TextView::msgUnfocus(msg);
}
void Giant::draw() {
Commit: ed0cf5b1ad1233ddee2df39149a5cf123e1b06be
https://github.com/scummvm/scummvm/commit/ed0cf5b1ad1233ddee2df39149a5cf123e1b06be
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Fix switching character infos then pressing Escape
Changed paths:
engines/mm/mm1/views/character_info.cpp
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 707f10a1cf3..5e0da1dd105 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -267,7 +267,7 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
if (_state == DISPLAY) {
g_globals->_currCharacter = &g_globals->_party[
msg._action - KEYBIND_VIEW_PARTY1];
- addView();
+ redraw();
return true;
} else if (_state == TRADE_WITH) {
_state = TRADE_KIND;
Commit: 467b88f5708e1b7011231383df58b2ff80e453bd
https://github.com/scummvm/scummvm/commit/467b88f5708e1b7011231383df58b2ff80e453bd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Fix view area incorrectly showing some messages
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/game/view_base.h
engines/mm/mm1/messages.h
engines/mm/mm1/views/search.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 9febbd56715..7ab74af9bd5 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -239,6 +239,7 @@ public:
MESSAGE(MouseUp);
MESSAGE(Action);
MESSAGE(Game);
+ MESSAGE(Header);
MESSAGE(Info);
MESSAGE(Value);
MESSAGE(DrawGraphic);
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index f51cee39429..7b5f73f8f13 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -115,14 +115,17 @@ bool ViewBase::msgGame(const GameMessage &msg) {
replaceView("Game");
update();
return true;
- } else {
- _descriptionLine = msg._name;
- draw();
}
return TextView::msgGame(msg);
}
+bool ViewBase::msgHeader(const HeaderMessage &msg) {
+ _descriptionLine = msg._name;
+ draw();
+ return true;
+}
+
void ViewBase::turnLeft() {
g_globals->_maps.turnLeft();
update();
diff --git a/engines/mm/mm1/game/view_base.h b/engines/mm/mm1/game/view_base.h
index fd8f5ae5bf9..ca2180123e6 100644
--- a/engines/mm/mm1/game/view_base.h
+++ b/engines/mm/mm1/game/view_base.h
@@ -75,6 +75,7 @@ public:
virtual ~ViewBase() {}
bool msgFocus(const FocusMessage &msg) override;
+ bool msgHeader(const HeaderMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
bool msgValue(const ValueMessage &msg) override;
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 33e2fa9f90c..8ef0ff64d91 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -78,6 +78,13 @@ struct GameMessage : public Message {
_name(name) {}
};
+struct HeaderMessage : public Message {
+ Common::String _name;
+ HeaderMessage() : Message() {}
+ HeaderMessage(const Common::String &name) : Message(),
+ _name(name) {}
+};
+
struct Line : public Common::Point {
Common::String _text;
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 502c4c1b9b3..6feace19fc7 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -147,7 +147,7 @@ void Search::timeout() {
}
// Show the name of the container type in the game view
- send("View", GameMessage(
+ send("View", HeaderMessage(
STRING[Common::String::format("dialogs.search.containers.%d",
g_globals->_treasure._container)]
));
Commit: dc11da0e2045cceb8c30cb9194c5d957f8d0a0ed
https://github.com/scummvm/scummvm/commit/dc11da0e2045cceb8c30cb9194c5d957f8d0a0ed
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Cleanup of character info TODOs
Changed paths:
engines/mm/mm1/views/character_info.cpp
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 5e0da1dd105..803b40d2349 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -428,7 +428,7 @@ void CharacterInfo::equipItem(uint index) {
break;
}
- warning("TODO: c field58");
+ c.updateResistances();
c.updateAttributes();
c.updateAC();
@@ -478,9 +478,9 @@ void CharacterInfo::removeItem(uint index) {
c._backpack.add(itemId, item14);
if (item._val10) {
- // TODO: This block doesn't make sense in the original.
- // It uses the item._equipMode as an arbitrary array
- // index into the character data.
+ // TODO: _equipMode is used as a character offset. Need to
+ // find an example that calls it so I know what area of
+ // the character updates are being done to
error("TODO: item flag in remove item");
}
@@ -584,6 +584,7 @@ void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
} else {
+ // TODO: find out area of Character _effectId is used as an offset for
error("TODO: _effectId used as a character offset to increase attribute?");
if (g_globals->_combatEffectCtr)
@@ -626,6 +627,7 @@ void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped
Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
} else {
+ // TODO: find out area of Character _effectId is used as an offset for
error("TODO: _effectId used as a character offset to increase attribute?");
if (g_globals->_nonCombatEffectCtr)
Commit: 71e4883db9bd05892357170fc35e4afda9c77f1f
https://github.com/scummvm/scummvm/commit/71e4883db9bd05892357170fc35e4afda9c77f1f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Compilation fixes
Changed paths:
engines/mm/mm1/data/trap.h
engines/mm/mm1/maps/map54.cpp
engines/mm/mm1/views/search.cpp
diff --git a/engines/mm/mm1/data/trap.h b/engines/mm/mm1/data/trap.h
index 160f43bd644..8a86b9fc6c2 100644
--- a/engines/mm/mm1/data/trap.h
+++ b/engines/mm/mm1/data/trap.h
@@ -49,6 +49,8 @@ protected:
byte _condition = 0;
virtual void trap();
+public:
+ virtual ~TrapData() {}
};
} // namespace MM1
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index 5d711addedd..c102fc9fcaf 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -67,8 +67,8 @@ void Map54::special00() {
// Check for flag
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- if ((c._flags[13] & (CHARFLAG13_1 or CHARFLAG13_2 or CHARFLAG13_4 or CHARFLAG13_8 or CHARFLAG13_10)) !=
- (CHARFLAG13_1 or CHARFLAG13_2 or CHARFLAG13_4 or CHARFLAG13_8 or CHARFLAG13_10)) {
+ if ((c._flags[13] & (CHARFLAG13_1 | CHARFLAG13_2 | CHARFLAG13_4 | CHARFLAG13_8 | CHARFLAG13_10)) !=
+ (CHARFLAG13_1 | CHARFLAG13_2 | CHARFLAG13_4 | CHARFLAG13_8 | CHARFLAG13_10)) {
g_maps->_mapPos.y++;
updateGame();
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 6feace19fc7..fd136de81b2 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -74,6 +74,9 @@ void Search::draw() {
writeString(20, 3, STRING["dialogs.search.options3"]);
escToGoBack(0, 3);
break;
+
+ default:
+ break;
}
}
@@ -98,6 +101,8 @@ bool Search::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_3:
detectMagicTrap();
break;
+ default:
+ break;
}
break;
@@ -168,6 +173,9 @@ void Search::timeout() {
case WHO_WILL_TRY:
draw();
break;
+
+ default:
+ break;
}
}
Commit: 75184f63a8e816b1aa721f61776ff981f8b11f72
https://github.com/scummvm/scummvm/commit/75184f63a8e816b1aa721f61776ff981f8b11f72
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Remove castUnknown for proper removeCharge
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/character_info.h
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 90f9e6f6060..767ad4df67e 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -521,10 +521,6 @@ Common::String Character::getConditionString() const {
return result;
}
-void Character::castUnknown() {
- warning("TODO: castUnknown method");
-}
-
void Character::rest() {
// Characters with a bad condition like
// being stoned can't rest
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 37e492ba375..dff27d0c1f4 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -516,8 +516,6 @@ struct Character : public PrimaryAttributes {
*/
Common::String getConditionString() const;
- void castUnknown();
-
/**
* Rest the character
*/
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 803b40d2349..f322c963679 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -237,21 +237,24 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
case USE: {
Character &c = *g_globals->_currCharacter;
+ Inventory *inv;
Inventory::Entry *invEntry;
if (msg.keycode >= Common::KEYCODE_1 && msg.keycode <= Common::KEYCODE_6 &&
(msg.keycode - Common::KEYCODE_1) < (int)c._equipped.size()) {
+ inv = &c._equipped;
invEntry = &c._equipped[msg.keycode - Common::KEYCODE_1];
} else if (msg.keycode >= Common::KEYCODE_a && msg.keycode <= Common::KEYCODE_f &&
(msg.keycode - Common::KEYCODE_a) < (int)c._backpack.size()) {
+ inv = &c._backpack;
invEntry = &c._backpack[msg.keycode - Common::KEYCODE_a];
} else {
break;
}
if (dynamic_cast<Views::Combat *>(g_events->priorView()) != nullptr)
- combatUseItem(*invEntry, msg.keycode >= Common::KEYCODE_a);
+ combatUseItem(*inv, *invEntry, msg.keycode >= Common::KEYCODE_a);
else
- nonCombatUseItem(*invEntry, msg.keycode >= Common::KEYCODE_a);
+ nonCombatUseItem(*inv, *invEntry, msg.keycode >= Common::KEYCODE_a);
break;
}
default:
@@ -569,7 +572,7 @@ void CharacterInfo::tradeHowMuch() {
);
}
-void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
+void CharacterInfo::combatUseItem(Inventory &inv, Inventory::Entry &invEntry, bool isEquipped) {
Item *item = g_globals->_items.getItem(invEntry._id);
Common::String msg;
@@ -579,6 +582,8 @@ void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
} else if (item->_equipMode == IS_EQUIPPABLE || isEquipped) {
if (invEntry._charges) {
g_globals->_combatEffectCtr++;
+ inv.removeCharge(&invEntry);
+
if (item->_effectId == 0xff) {
setSpell(item->_spellId, 0, 0);
Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
@@ -612,7 +617,7 @@ void CharacterInfo::combatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
delaySeconds(3);
}
-void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped) {
+void CharacterInfo::nonCombatUseItem(Inventory &inv, Inventory::Entry &invEntry, bool isEquipped) {
Item *item = g_globals->_items.getItem(invEntry._id);
Common::String msg;
@@ -622,6 +627,8 @@ void CharacterInfo::nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped
} else if (item->_equipMode == IS_EQUIPPABLE || isEquipped) {
if (invEntry._charges) {
g_globals->_nonCombatEffectCtr++;
+ inv.removeCharge(&invEntry);
+
if (item->_effectId == 0xff) {
setSpell(item->_spellId, 0, 0);
Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index 6a8fc92641c..c888d7781db 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -71,12 +71,12 @@ private:
/**
* Using an item during combat
*/
- void combatUseItem(Inventory::Entry &invEntry, bool isEquipped);
+ void combatUseItem(Inventory &inv, Inventory::Entry &invEntry, bool isEquipped);
/**
* Using an item outside of combat
*/
- void nonCombatUseItem(Inventory::Entry &invEntry, bool isEquipped);
+ void nonCombatUseItem(Inventory &inv, Inventory::Entry &invEntry, bool isEquipped);
public:
CharacterInfo() : CharacterBase("CharacterInfo") {}
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index a275c9508f2..a4ea075e984 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -189,8 +189,6 @@ void CastSpell::performSpell(Character *chr) {
c._sp._current = MAX(c._sp._current - _requiredSp, 0);
c._gems = MAX(c._gems - _requiredGems, 0);
- c.castUnknown();
-
if (!isMagicAllowed()) {
spellDone(STRING["dialogs.misc.magic_doesnt_work"], 5);
} else {
Commit: adf42ee7e360e7498abdab68ad398fad69d606b5
https://github.com/scummvm/scummvm/commit/adf42ee7e360e7498abdab68ad398fad69d606b5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Rename remaining unknown character fields
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/views/create_characters.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/maps/giant.cpp
engines/mm/mm1/views/maps/prisoners.cpp
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/unlock.cpp
engines/mm/mm1/views_enh/locations/temple.cpp
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 767ad4df67e..27c94ef2894 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -203,9 +203,9 @@ void Character::synchronize(Common::Serializer &s) {
_physicalAttr.synchronize(s);
_missileAttr.synchronize(s);
- s.syncAsByte(_v6c);
+ s.syncAsByte(_trapCtr);
s.syncAsByte(_quest);
- s.syncAsByte(_v6e);
+ s.syncAsByte(_worthiness);
s.syncAsByte(_alignmentCtr);
s.syncBytes(_flags, 14);
@@ -242,7 +242,7 @@ void Character::clear() {
_resistances._s._fear.clear();
_resistances._s._poison.clear();
_resistances._s._psychic.clear();
- _v6c = _alignmentCtr = 0;
+ _trapCtr = _alignmentCtr = 0;
Common::fill(&_flags[0], &_flags[8], 0);
}
@@ -280,7 +280,7 @@ Character::LevelIncrease Character::increaseLevel() {
++_age;
if (_age._base > 220)
_age._base = 220;
- _v6c += 2;
+ _trapCtr += 2;
int classNum = _class == NONE ? ROBBER : _class;
int newHP = g_engine->getRandomNumber(CLASS_HP_PER_LEVEL[classNum - 1]);
@@ -629,9 +629,9 @@ size_t Character::getPerformanceTotal() const {
+ _resistances.getPerformanceTotal()
+ _physicalAttr.getPerformanceTotal()
+ _missileAttr.getPerformanceTotal()
- + _v6c
+ + _trapCtr
+ _quest
- + _v6e
+ + _worthiness
+ _alignmentCtr
+ totalFlags;
}
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index dff27d0c1f4..12779b97098 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -438,11 +438,10 @@ struct Character : public PrimaryAttributes {
Inventory _backpack;
Resistances _resistances;
- // TODO: Figure out what these are
AttributePair _physicalAttr, _missileAttr;
- byte _v6c;
+ byte _trapCtr = 0;
byte _quest = 0;
- byte _v6e;
+ byte _worthiness;
int _alignmentCtr;
byte _flags[14];
byte _lastField = 0;
diff --git a/engines/mm/mm1/views/create_characters.cpp b/engines/mm/mm1/views/create_characters.cpp
index 4119a208019..4c7c71db9c3 100644
--- a/engines/mm/mm1/views/create_characters.cpp
+++ b/engines/mm/mm1/views/create_characters.cpp
@@ -98,7 +98,7 @@ void CreateCharacters::NewCharacter::save() {
break;
case ROBBER:
setHP(8);
- re._v6c = 50;
+ re._trapCtr = 50;
break;
default:
break;
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index d0235f28e2e..181ae62e1b5 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -203,7 +203,7 @@ void Temple::donate() {
townNum = 1;
--townNum;
- c._v6e |= DONATE_VALS[townNum];
+ c._worthiness |= DONATE_VALS[townNum];
draw();
if (g_engine->getRandomNumber(15) == 10) {
diff --git a/engines/mm/mm1/views/maps/giant.cpp b/engines/mm/mm1/views/maps/giant.cpp
index bad954c7f8c..66307374b39 100644
--- a/engines/mm/mm1/views/maps/giant.cpp
+++ b/engines/mm/mm1/views/maps/giant.cpp
@@ -95,15 +95,15 @@ void Giant::timeout() {
void Giant::worthy() {
Character &c = *g_globals->_currCharacter;
- int val = ((c._v6e + 1) / 2) * 256;
+ int val = ((c._worthiness + 1) / 2) * 256;
c._exp += val;
Common::String line = Common::String::format(
- STRING["maps.map30.worthy"].c_str(), '0' + (c._v6e / 5));
+ STRING["maps.map30.worthy"].c_str(), '0' + (c._worthiness / 5));
line = Common::String::format("%s%d %s",
line.c_str(), val, STRING["maps.map30.experience"].c_str());
- if (c._v6e & 0x80) {
+ if (c._worthiness & 0x80) {
int attrNum = getRandomNumber(7) - 1;
line += Common::String::format(", +3 %s",
STRING[Common::String::format("maps.map30.attributes.%d", attrNum)].c_str());
@@ -113,7 +113,7 @@ void Giant::worthy() {
attrib._current = attrib._base = attrib._base + 3;
}
- c._v6e = 0;
+ c._worthiness = 0;
clearSurface();
writeString(0, 1, line);
diff --git a/engines/mm/mm1/views/maps/prisoners.cpp b/engines/mm/mm1/views/maps/prisoners.cpp
index ac4dd7a844d..327660d6ba7 100644
--- a/engines/mm/mm1/views/maps/prisoners.cpp
+++ b/engines/mm/mm1/views/maps/prisoners.cpp
@@ -74,7 +74,7 @@ bool Prisoner::msgKeypress(const KeypressMessage &msg) {
if (!(c._flags[1] & _flag)) {
c._flags[1] |= _flag;
if (align == c._alignment)
- c._v6e += 32;
+ c._worthiness += 32;
}
}
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index fd136de81b2..bb06aab38f9 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -199,7 +199,7 @@ void Search::findRemoveTrap2() {
Character &c = *g_globals->_currCharacter;
if (g_globals->_treasure._trapType == 1) {
- byte val = c._v6c;
+ byte val = c._trapCtr;
if (getRandomNumber(val >= 100 ? val + 5 : 100) >= val) {
// TODO
}
diff --git a/engines/mm/mm1/views/unlock.cpp b/engines/mm/mm1/views/unlock.cpp
index aa1987da97a..bef7d72c39e 100644
--- a/engines/mm/mm1/views/unlock.cpp
+++ b/engines/mm/mm1/views/unlock.cpp
@@ -107,7 +107,7 @@ void Unlock::charSelected(uint charIndex) {
int val = g_maps->_currentMap->dataByte(Maps::MAP_49) * 4 +
getRandomNumber(100);
- if (val < c._v6c) {
+ if (val < c._trapCtr) {
g_maps->_currentMap->unlockDoor();
send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
index b6c725aad9a..cc3fa2d73ab 100644
--- a/engines/mm/mm1/views_enh/locations/temple.cpp
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -207,7 +207,7 @@ void Temple::donate() {
townNum = 1;
--townNum;
- c._v6e |= DONATE_VALS[townNum];
+ c._worthiness |= DONATE_VALS[townNum];
draw();
if (g_engine->getRandomNumber(15) == 10) {
Commit: 673c1ff1e2a0db9b2c1930a33f9e0c1ab219dd42
https://github.com/scummvm/scummvm/commit/673c1ff1e2a0db9b2c1930a33f9e0c1ab219dd42
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Fix sign text in map 0
Changed paths:
engines/mm/mm1/maps/map00.cpp
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index 478c523e31f..a6f2685ed66 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -222,27 +222,27 @@ void Map00::special17() {
void Map00::special18() {
send(SoundMessage(
- 2, 0, STRING["maps.map00.sign"],
+ 2, 0, STRING["maps.sign"],
6, 1, STRING["maps.map00.temple"]
));
}
void Map00::special19() {
send(SoundMessage(
- 2, 0, STRING["maps.map00.sign"],
+ 2, 0, STRING["maps.sign"],
6, 1, STRING["maps.map00.jail"]
));
}
void Map00::special20() {
send(SoundMessage(
- 2, 0, STRING["maps.map00.sign"],
+ 2, 0, STRING["maps.sign"],
6, 1, STRING["maps.map00.tavern"]
));
}
void Map00::special21() {
send(SoundMessage(
- 2, 0, STRING["maps.map00.sign"],
+ 2, 0, STRING["maps.sign"],
6, 1, STRING["maps.map00.training"]
));
}
Commit: 53dd26631ba4eff74b84b0e58cccf5be9dc6129c
https://github.com/scummvm/scummvm/commit/53dd26631ba4eff74b84b0e58cccf5be9dc6129c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:33+01:00
Commit Message:
MM: MM1: Stub implementation for is key pressed, for maps
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map37.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index f62d9d24d3b..a9a4d519077 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -166,6 +166,14 @@ void Events::addAction(KeybindingAction action) {
focusedView()->msgAction(ActionMessage(action));
}
+bool Events::isKeypressPending() const {
+ // TODO: Currently the engine doesn't cache keypresses, but rather
+ // processes them immediately after each is pulled from the
+ // SDL event queue. So for this to work, we'd need to rework
+ // the event handler code
+ return false;
+}
+
/*------------------------------------------------------------------------*/
Bounds::Bounds(Common::Rect &innerBounds) :
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 7ab74af9bd5..106170c4f29 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -340,6 +340,11 @@ public:
*/
void addAction(KeybindingAction action);
+ /**
+ * Checks whether a keypress is pending
+ */
+ bool isKeypressPending() const;
+
void draw() override {}
bool tick() override {
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 7b5f73f8f13..ba71abfd76c 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -52,7 +52,6 @@ void ViewBase::update() {
if ((map[Maps::MAP_FLAGS] & 1) && !g_globals->_activeSpells._s.light) {
darkness:
- // TODO
_isDark = true;
}
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index 23d31edd31e..b50a162236d 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -172,7 +172,10 @@ void Map23::special12() {
_states[g_maps->_mapOffset] = 0xff;
_walls[g_maps->_mapOffset] = 162;
- g_maps->clearSpecial();
+ if (g_events->isKeypressPending()) {
+ send(InfoMessage());
+ g_maps->clearSpecial();
+ }
}
void Map23::special13() {
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index 1943093c6c7..de7920e3db8 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -46,9 +46,9 @@ void Map37::special() {
}
}
- // TODO: figure out unknown method that determines whether
- // the floor spins or not
- if (true) {
+ if (g_events->isKeypressPending()) {
+ send(InfoMessage());
+ } else {
send(SoundMessage(STRING["maps.map37.spins"]));
g_events->addAction(KEYBIND_TURN_LEFT);
}
Commit: 556c6e5fd81f7094c745fa457a9ec986a0d51523
https://github.com/scummvm/scummvm/commit/556c6e5fd81f7094c745fa457a9ec986a0d51523
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Fix writeString to handle color reversed characters
Changed paths:
engines/mm/mm1/views/text_view.cpp
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 85d7982656d..87f17e91d14 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -60,11 +60,7 @@ void TextView::writeChar(int x, int y, unsigned char c) {
void TextView::writeString(const Common::String &str) {
for (const unsigned char *s = (const unsigned char *)str.c_str(); *s; ++s) {
- if (*s & 0x80)
- warning("TODO: Unknown high-bit set in string character");
-
- char c = (char)(*s & 0x7f);
- writeChar(c);
+ writeChar(*s);
}
}
Commit: ae64653caa31aa12c255461827374a09c85cc666
https://github.com/scummvm/scummvm/commit/ae64653caa31aa12c255461827374a09c85cc666
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Added a Roster update method
Changed paths:
engines/mm/mm1/data/roster.cpp
engines/mm/mm1/data/roster.h
engines/mm/mm1/views/locations/inn.cpp
diff --git a/engines/mm/mm1/data/roster.cpp b/engines/mm/mm1/data/roster.cpp
index 551876300c0..b51438ccc3f 100644
--- a/engines/mm/mm1/data/roster.cpp
+++ b/engines/mm/mm1/data/roster.cpp
@@ -61,6 +61,45 @@ void Roster::load() {
}
}
+void Roster::update(const IntArray &charNums) {
+ int fallbackIndex = ROSTER_COUNT - 1;
+
+ for (int i = (int)g_globals->_party.size() - 1; i >= 0; --i) {
+ const Character &c = g_globals->_party[i];
+
+ int destIndex;
+ if (charNums.size() == g_globals->_party.size() &&
+ charNums[i] < ROSTER_COUNT &&
+ _items[charNums[i]]._name == c._name) {
+ // Started game from title screen and set up party,
+ // so we known the correct roster index already
+ destIndex = charNums[i];
+
+ } else {
+ for (destIndex = 0; destIndex < ROSTER_COUNT; ++destIndex) {
+ if (_items[destIndex]._name == c._name)
+ break;
+ }
+
+ if (destIndex == ROSTER_COUNT) {
+ // Couldn't find a matching name in roster to update
+ for (destIndex = 0; destIndex < ROSTER_COUNT; ++destIndex) {
+ if (!_towns[destIndex])
+ break;
+ }
+
+ if (destIndex == ROSTER_COUNT)
+ // Replace entries at the end of the roster
+ destIndex = fallbackIndex--;
+ }
+ }
+
+ // Copy the entry into the roster
+ _items[destIndex] = c;
+ _towns[destIndex] = (Maps::TownId)g_maps->_currentMap->dataByte(Maps::MAP_ID);
+ }
+}
+
void Roster::save() {
Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
rosterSaveName());
diff --git a/engines/mm/mm1/data/roster.h b/engines/mm/mm1/data/roster.h
index 8ca594a7619..4c33ad9d67f 100644
--- a/engines/mm/mm1/data/roster.h
+++ b/engines/mm/mm1/data/roster.h
@@ -24,6 +24,7 @@
#include "common/serializer.h"
#include "mm/mm1/data/character.h"
+#include "mm/mm1/data/int_array.h"
#include "mm/mm1/maps/maps.h"
namespace MM {
@@ -53,6 +54,11 @@ public:
*/
void load();
+ /**
+ * Updates the roster from the party
+ */
+ void update(const IntArray &charNums);
+
/**
* Save the roster
*/
diff --git a/engines/mm/mm1/views/locations/inn.cpp b/engines/mm/mm1/views/locations/inn.cpp
index 9218defcd26..5ef2a964f81 100644
--- a/engines/mm/mm1/views/locations/inn.cpp
+++ b/engines/mm/mm1/views/locations/inn.cpp
@@ -29,6 +29,7 @@ namespace Locations {
bool Inn::msgFocus(const FocusMessage &msg) {
// Save the roster
+ g_globals->_roster.update(_partyChars);
g_globals->_roster.save();
// Get a list of characters in the town
Commit: d418c2f93051c88bd57e9ca4cd499e8400bf2610
https://github.com/scummvm/scummvm/commit/d418c2f93051c88bd57e9ca4cd499e8400bf2610
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Repurpose unused last byte of character as portrait
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 27c94ef2894..48345d819e5 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -208,8 +208,7 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_worthiness);
s.syncAsByte(_alignmentCtr);
s.syncBytes(_flags, 14);
-
- s.skip(1);
+ s.syncAsByte(_portrait);
}
void Character::clear() {
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 12779b97098..254c22ef2dc 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -444,7 +444,7 @@ struct Character : public PrimaryAttributes {
byte _worthiness;
int _alignmentCtr;
byte _flags[14];
- byte _lastField = 0;
+ byte _portrait = 0;
// Non persistent fields
byte _numDrinks = 0;
Commit: 1d9b52d78c8e3b0e17f749523263f7e96c66d487
https://github.com/scummvm/scummvm/commit/1d9b52d78c8e3b0e17f749523263f7e96c66d487
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Added Character constructor
Changed paths:
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 48345d819e5..7888d90a42e 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -154,6 +154,10 @@ size_t Inventory::getPerformanceTotal() const {
/*------------------------------------------------------------------------*/
+Character::Character() : PrimaryAttributes() {
+ Common::fill(&_flags[0], &_flags[14], 0);
+}
+
void Character::synchronize(Common::Serializer &s) {
s.syncBytes((byte *)_name, 16);
s.syncAsByte(_sex);
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 254c22ef2dc..3158992c912 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -441,14 +441,16 @@ struct Character : public PrimaryAttributes {
AttributePair _physicalAttr, _missileAttr;
byte _trapCtr = 0;
byte _quest = 0;
- byte _worthiness;
- int _alignmentCtr;
+ byte _worthiness = 0;
+ byte _alignmentCtr = 0;
byte _flags[14];
byte _portrait = 0;
// Non persistent fields
byte _numDrinks = 0;
+ Character();
+
/**
* Handles save/loading a character
*/
Commit: 2b84d6db6489e7f5441bba45bbf6f3b715f5bcdf
https://github.com/scummvm/scummvm/commit/2b84d6db6489e7f5441bba45bbf6f3b715f5bcdf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Adding saving code
Changed paths:
engines/mm/mm1/data/treasure.cpp
engines/mm/mm1/data/treasure.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/game/spell_casting.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/mm1.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/data/treasure.cpp b/engines/mm/mm1/data/treasure.cpp
index 875668061cc..5d159fc5239 100644
--- a/engines/mm/mm1/data/treasure.cpp
+++ b/engines/mm/mm1/data/treasure.cpp
@@ -46,5 +46,9 @@ bool Treasure::present() const {
return false;
}
+void Treasure::synchronize(Common::Serializer &s) {
+ s.syncBytes(_data, 9);
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
index c1206791761..fbf4cad7873 100644
--- a/engines/mm/mm1/data/treasure.h
+++ b/engines/mm/mm1/data/treasure.h
@@ -23,6 +23,7 @@
#define MM1_DATA_TREASURE_H
#include "common/scummsys.h"
+#include "common/serializer.h"
namespace MM {
namespace MM1 {
@@ -56,6 +57,11 @@ public:
* Returns true if any treasure has been assigned
*/
bool present() const;
+
+ /**
+ * Synchronize savegame data
+ */
+ void synchronize(Common::Serializer &s);
};
} // namespace MM1
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index a9a4d519077..f40e29998cb 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -146,6 +146,15 @@ void Events::popView() {
}
}
+bool Events::isPresent(const Common::String &name) const {
+ for (uint i = 0; i < _views.size(); ++i) {
+ if (_views[i]->_name == name)
+ return true;
+ }
+
+ return false;
+}
+
void Events::clearViews() {
if (!_views.empty())
focusedView()->msgUnfocus(UnfocusMessage());
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 106170c4f29..c754dccbc0e 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -321,6 +321,12 @@ public:
_views[_views.size() - 2];
}
+ /**
+ * Returns true if a view of a given name is present
+ * at all in the visible view stack
+ */
+ bool isPresent(const Common::String &name) const;
+
Graphics::Screen *getScreen() const {
return _screen;
}
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index d5fabe1c03c..56db41444c7 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -21,6 +21,7 @@
#include "mm/mm1/game/spell_casting.h"
#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/views/combat.h"
#include "mm/mm1/globals.h"
namespace MM {
@@ -116,9 +117,9 @@ void SpellCasting::setSpell(int spellIndex, int requiredSp, int requiredGems) {
Maps::Map &map = *g_maps->_currentMap;
- if (!g_globals->_inCombat && SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
+ if (!isInCombat() && SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
_spellState = SS_COMBAT_ONLY;
- else if (g_globals->_inCombat && SPELL_FLAGS[spellIndex] & SF_NONCOMBAT_ONLY)
+ else if (isInCombat() && SPELL_FLAGS[spellIndex] & SF_NONCOMBAT_ONLY)
_spellState = SS_NONCOMBAT_ONLY;
else if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) &&
!(map[Maps::MAP_ID] & 0x80))
@@ -153,11 +154,15 @@ Common::String SpellCasting::getSpellError() const {
break;
}
- if (!g_globals->_inCombat)
+ if (!isInCombat())
msg = Common::String::format("*** %s ***", msg.c_str());
return msg;
}
+bool SpellCasting::isInCombat() const {
+ return g_events->isPresent("Combat");
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spell_casting.h b/engines/mm/mm1/game/spell_casting.h
index 40cc8a3cedd..383db8287f0 100644
--- a/engines/mm/mm1/game/spell_casting.h
+++ b/engines/mm/mm1/game/spell_casting.h
@@ -38,6 +38,11 @@ enum SpellState {
* Support class for handling spell casting logic
*/
class SpellCasting {
+private:
+ /**
+ * Returns true if combat is in progress
+ */
+ bool isInCombat() const;
protected:
int _spellIndex = 0;
int _requiredSp = 0, _requiredGems = 0;
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index c49706c9255..0184e0a2d71 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -95,5 +95,26 @@ bool Globals::load(bool isEnhanced) {
return true;
}
+void Globals::synchronize(Common::Serializer &s) {
+ s.syncAsByte(_startingTown);
+
+ // Sync the party
+ int partySize = _party.size();
+ s.syncAsByte(partySize);
+ if (s.isLoading())
+ _party.resize(partySize);
+
+ for (int i = 0; i < partySize; ++i)
+ _party[i].synchronize(s);
+
+ // Sync map data and visited tiles
+ _maps.synchronize(s);
+
+ // Sync treasure data
+ _treasure.synchronize(s);
+
+ _currCharacter = nullptr;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 18ac6212423..0d49a45e070 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -22,6 +22,7 @@
#ifndef MM1_GLOBALS_H
#define MM1_GLOBALS_H
+#include "common/serializer.h"
#include "graphics/font.h"
#include "mm/utils/bitmap_font.h"
#include "mm/utils/strings_data.h"
@@ -55,7 +56,6 @@ public:
Treasure _treasure;
byte _delay = 5;
int _nonCombatEffectCtr = 0, _combatEffectCtr = 0;
- bool _inCombat = false;
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
@@ -81,6 +81,11 @@ public:
assert(_strings.contains(name));
return _strings[name];
}
+
+ /**
+ * Saves or loads global data to/from savegames
+ */
+ void synchronize(Common::Serializer &s);
};
extern Globals *g_globals;
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index a67d9bfbc93..4213accea26 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -29,11 +29,15 @@
#include "mm/mm1/mm1.h"
#include "mm/mm1/console.h"
#include "mm/mm1/gfx/gfx.h"
-#include "mm/xeen/files.h"
+//#include "mm/xeen/files.h"
+#include "mm/mm1/views/game.h"
+#include "mm/mm1/views_enh/game.h"
namespace MM {
namespace MM1 {
+#define SAVEGAME_VERSION 1
+
MM1Engine *g_engine = nullptr;
MM1Engine::MM1Engine(OSystem *syst, const MightAndMagicGameDescription *gameDesc)
@@ -126,16 +130,38 @@ bool MM1Engine::hasFeature(EngineFeature f) const {
}
bool MM1Engine::canSaveGameStateCurrently() {
- return !g_globals->_inCombat;
+ if (!g_events)
+ return false;
+
+ UIElement *view = g_events->focusedView();
+ return dynamic_cast<Views::Game *>(view) != nullptr ||
+ dynamic_cast<ViewsEnh::Game *>(view) != nullptr;
}
bool MM1Engine::canLoadGameStateCurrently() {
+ if (!g_events)
+ return false;
+
+ // Loading savegames can be done in any view, since we can
+ // just remove them all and add the game view
return true;
}
-Common::Error MM1Engine::loadGameStream(Common::SeekableReadStream *stream) {
- // TODO: Loading savegames
- g_globals->_inCombat = false;
+Common::Error MM1Engine::synchronizeSave(Common::Serializer &s) {
+ // Get/set the version
+ byte version = SAVEGAME_VERSION;
+ s.syncAsByte(version);
+ if (version > SAVEGAME_VERSION)
+ return Common::kReadingFailed;
+ s.setVersion(version);
+
+ // Sync globals
+ g_globals->synchronize(s);
+
+ // If we're loading a savegame, switch to the game view
+ if (s.isLoading())
+ g_events->replaceView("Game", true);
+
return Common::kNoError;
}
diff --git a/engines/mm/mm1/mm1.h b/engines/mm/mm1/mm1.h
index f5dc49de4b0..7b25cfc61cd 100644
--- a/engines/mm/mm1/mm1.h
+++ b/engines/mm/mm1/mm1.h
@@ -23,6 +23,7 @@
#define MM1_MM1_H
#include "common/random.h"
+#include "common/serializer.h"
#include "mm/detection.h"
#include "mm/mm.h"
#include "mm/mm1/events.h"
@@ -77,7 +78,26 @@ public:
*/
bool canLoadGameStateCurrently() override;
- Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
+ /**
+ * Saves or loads a savegame
+ */
+ Common::Error synchronizeSave(Common::Serializer &s);
+
+ /**
+ * Load a savegame
+ */
+ Common::Error loadGameStream(Common::SeekableReadStream *stream) override {
+ Common::Serializer s(stream, nullptr);
+ return synchronizeSave(s);
+ }
+
+ /**
+ * Save a savegame
+ */
+ Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override {
+ Common::Serializer s(nullptr, stream);
+ return synchronizeSave(s);
+ }
};
extern MM1Engine *g_engine;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index c1b0aef1783..88f47994a62 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -168,7 +168,6 @@ void Combat::timeout() {
spells._s.power_shield = 0;
close();
- g_globals->_inCombat = false;
g_events->send("Game", GameMessage("UPDATE"));
return;
}
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 81cef311828..6fdabdad96e 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -34,7 +34,6 @@ Encounter::Encounter() : TextView("Encounter") {
bool Encounter::msgFocus(const FocusMessage &msg) {
_mode = ALERT;
- g_globals->_inCombat = true;
return true;
}
@@ -247,7 +246,6 @@ bool Encounter::msgKeypress(const KeypressMessage &msg) {
void Encounter::encounterEnded() {
close();
- g_globals->_inCombat = false;
g_events->send("Game", GameMessage("UPDATE"));
}
Commit: 29646889fc019831a4e88b592a72c1822be680dc
https://github.com/scummvm/scummvm/commit/29646889fc019831a4e88b592a72c1822be680dc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: EXperiments using new saves format for MM1, old code for Xeen
Changed paths:
A engines/mm/xeen/meta_engine.cpp
A engines/mm/xeen/meta_engine.h
engines/mm/meta_engine.cpp
engines/mm/module.mk
diff --git a/engines/mm/meta_engine.cpp b/engines/mm/meta_engine.cpp
index 37407732ad6..52eb88a2539 100644
--- a/engines/mm/meta_engine.cpp
+++ b/engines/mm/meta_engine.cpp
@@ -31,17 +31,21 @@
#include "mm/detection.h"
#include "mm/mm1/mm1.h"
#include "mm/xeen/xeen.h"
+#include "mm/xeen/meta_engine.h"
#include "mm/xeen/worldofxeen/worldofxeen.h"
#include "mm/xeen/swordsofxeen/swordsofxeen.h"
-#define MAX_SAVES 99
-
class MMMetaEngine : public AdvancedMetaEngine {
private:
/**
* Gets the game Id given a target string
*/
static Common::String getGameId(const Common::String &target);
+
+ /**
+ * Returns true if the game is a Xeen game
+ */
+ static bool isXeenGame(const Common::String &target);
public:
const char *getName() const override {
return "mm";
@@ -49,9 +53,8 @@ public:
bool hasFeature(MetaEngineFeature f) const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
- SaveStateList listSaves(const char *target) const override;
int getMaximumSaveSlot() const override;
- void removeSaveState(const char *target, int slot) const override;
+ SaveStateList listSaves(const char *target) const override;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
Common::KeymapArray initKeymaps(const char *target) const override;
};
@@ -97,69 +100,24 @@ Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const
return Common::kNoError;
}
-SaveStateList MMMetaEngine::listSaves(const char *target) const {
- Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
- Common::StringArray filenames;
- Common::String saveDesc;
- Common::String pattern = Common::String::format("%s.###", target);
- MM::Xeen::XeenSavegameHeader header;
-
- filenames = saveFileMan->listSavefiles(pattern);
-
- SaveStateList saveList;
- for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
- const char *ext = strrchr(file->c_str(), '.');
- int slot = ext ? atoi(ext + 1) : -1;
-
- if (slot >= 0 && slot <= MAX_SAVES) {
- Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
-
- if (in) {
- if (MM::Xeen::SavesManager::readSavegameHeader(in, header))
- saveList.push_back(SaveStateDescriptor(this, slot, header._saveName));
-
- delete in;
- }
- }
- }
-
- Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
- return saveList;
-}
-
int MMMetaEngine::getMaximumSaveSlot() const {
- return MAX_SAVES;
+ return 999;
}
-void MMMetaEngine::removeSaveState(const char *target, int slot) const {
- Common::String filename = Common::String::format("%s.%03d", target, slot);
- g_system->getSavefileManager()->removeSavefile(filename);
+SaveStateList MMMetaEngine::listSaves(const char *target) const {
+ if (isXeenGame(target))
+ // Fallback original code for Xeen
+ return MM::Xeen::XeenMetaEngine::listSaves(this, target);
+
+ return AdvancedMetaEngine::listSaves(target);
}
SaveStateDescriptor MMMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
- Common::String filename = Common::String::format("%s.%03d", target, slot);
- Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
-
- if (f) {
- MM::Xeen::XeenSavegameHeader header;
- if (!MM::Xeen::SavesManager::readSavegameHeader(f, header, false)) {
- delete f;
- return SaveStateDescriptor();
- }
-
- delete f;
-
- // Create the return descriptor
- SaveStateDescriptor desc(this, slot, header._saveName);
- desc.setThumbnail(header._thumbnail);
- desc.setSaveDate(header._year, header._month, header._day);
- desc.setSaveTime(header._hour, header._minute);
- desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
-
- return desc;
- }
+ if (isXeenGame(target))
+ // Fallback original code for Xeen
+ return MM::Xeen::XeenMetaEngine::querySaveMetaInfos(this, target, slot);
- return SaveStateDescriptor();
+ return AdvancedMetaEngine::querySaveMetaInfos(target, slot);
}
Common::KeymapArray MMMetaEngine::initKeymaps(const char *target) const {
@@ -183,6 +141,14 @@ Common::String MMMetaEngine::getGameId(const Common::String &target) {
return gameId;
}
+bool MMMetaEngine::isXeenGame(const Common::String &target) {
+ Common::String gameId = getGameId(target);
+ if (gameId == "mm1" || gameId == "mm1_enh")
+ return false;
+
+ return true;
+}
+
#if PLUGIN_ENABLED_DYNAMIC(MM)
REGISTER_PLUGIN_DYNAMIC(MM, PLUGIN_TYPE_ENGINE, MMMetaEngine);
#else
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b787945133e..e44ebe79cb8 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -212,6 +212,7 @@ MODULE_OBJS := \
xeen/dialogs/dialogs_spells.o \
xeen/dialogs/dialogs_whowill.o \
xeen/dialogs/please_wait.o \
+ xeen/meta_engine.o \
xeen/character.o \
xeen/combat.o \
xeen/cutscenes.o \
diff --git a/engines/mm/xeen/meta_engine.cpp b/engines/mm/xeen/meta_engine.cpp
new file mode 100644
index 00000000000..62115f3094d
--- /dev/null
+++ b/engines/mm/xeen/meta_engine.cpp
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+#include "mm/xeen/meta_engine.h"
+#include "mm/xeen/events.h"
+#include "mm/xeen/saves.h"
+
+namespace MM {
+namespace Xeen {
+
+#define MAX_SAVES 999
+
+SaveStateDescriptor XeenMetaEngine::querySaveMetaInfos(const MetaEngine *metaEngine,
+ const char *target, int slot) {
+ Common::String filename = Common::String::format("%s.%03d", target, slot);
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
+
+ if (f) {
+ XeenSavegameHeader header;
+ if (!SavesManager::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
+
+ delete f;
+
+ // Create the return descriptor
+ SaveStateDescriptor desc(metaEngine, slot, header._saveName);
+ desc.setThumbnail(header._thumbnail);
+ desc.setSaveDate(header._year, header._month, header._day);
+ desc.setSaveTime(header._hour, header._minute);
+ desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME);
+
+ return desc;
+ }
+
+ return SaveStateDescriptor();
+}
+
+SaveStateList XeenMetaEngine::listSaves(const MetaEngine *metaEngine, const char *target) {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String saveDesc;
+ Common::String pattern = Common::String::format("%s.###", target);
+ MM::Xeen::XeenSavegameHeader header;
+
+ filenames = saveFileMan->listSavefiles(pattern);
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ const char *ext = strrchr(file->c_str(), '.');
+ int slot = ext ? atoi(ext + 1) : -1;
+
+ if (slot >= 0 && slot <= MAX_SAVES) {
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+
+ if (in) {
+ if (MM::Xeen::SavesManager::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(metaEngine, slot, header._saveName));
+
+ delete in;
+ }
+ }
+ }
+
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
+ return saveList;
+}
+
+} // End of namespace Xeen
+} // End of namespace MM
diff --git a/engines/mm/xeen/meta_engine.h b/engines/mm/xeen/meta_engine.h
new file mode 100644
index 00000000000..c9dc904db6b
--- /dev/null
+++ b/engines/mm/xeen/meta_engine.h
@@ -0,0 +1,41 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef XEEN_META_ENGINE_H
+#define XEEN_META_ENGINE_H
+
+#include "engines/advancedDetector.h"
+#include "engines/metaengine.h"
+
+namespace MM {
+namespace Xeen {
+
+class XeenMetaEngine {
+public:
+ static SaveStateDescriptor querySaveMetaInfos(const MetaEngine *metaEngine,
+ const char *target, int slot);
+ static SaveStateList listSaves(const MetaEngine *metaEngine, const char *target);
+};
+
+} // End of namespace Xeen
+} // End of namespace MM
+
+#endif
Commit: 4cf40ac22a772688cb7a5774eec055d633c66fb7
https://github.com/scummvm/scummvm/commit/4cf40ac22a772688cb7a5774eec055d633c66fb7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Further meta engine fixes for MM1 vs Xeen
Changed paths:
engines/mm/meta_engine.cpp
diff --git a/engines/mm/meta_engine.cpp b/engines/mm/meta_engine.cpp
index 52eb88a2539..f283cca3e16 100644
--- a/engines/mm/meta_engine.cpp
+++ b/engines/mm/meta_engine.cpp
@@ -53,7 +53,6 @@ public:
bool hasFeature(MetaEngineFeature f) const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
- int getMaximumSaveSlot() const override;
SaveStateList listSaves(const char *target) const override;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
Common::KeymapArray initKeymaps(const char *target) const override;
@@ -61,6 +60,7 @@ public:
bool MMMetaEngine::hasFeature(MetaEngineFeature f) const {
return
+ (f == kSavesUseExtendedFormat) ||
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
(f == kSupportsDeleteSave) ||
@@ -100,10 +100,6 @@ Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const
return Common::kNoError;
}
-int MMMetaEngine::getMaximumSaveSlot() const {
- return 999;
-}
-
SaveStateList MMMetaEngine::listSaves(const char *target) const {
if (isXeenGame(target))
// Fallback original code for Xeen
Commit: 754b2ca969ef8e7a48227214b3ed1b9a94525059
https://github.com/scummvm/scummvm/commit/754b2ca969ef8e7a48227214b3ed1b9a94525059
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Maps class cleanups
Changed paths:
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 0f6db05d709..27f87e79e43 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -122,7 +122,6 @@ static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
Maps::Maps() {
g_maps = this;
- Common::fill(&_data1[0], &_data1[32], 0);
_maps.push_back(new Map00());
_maps.push_back(new Map01());
@@ -191,7 +190,6 @@ void Maps::load(uint mapId) {
_mapId = mapId;
_currentMap = _maps[mapId];
_currentMap->load();
- Common::fill(&_data1[0], &_data1[32], 0);
}
void Maps::synchronize(Common::Serializer &s) {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index ebc3a84de35..d60df2608e2 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -58,6 +58,11 @@ private:
*/
uint getIndex(uint16 id, byte section);
+ /**
+ * Load a map
+ */
+ void load(uint mapId);
+
/**
* Loads tile graphics needed for rendering the 3d view
*/
@@ -87,7 +92,6 @@ public:
Map *_currentMap = nullptr;
byte _currentWalls = 0;
byte _currentState = 0;
- byte _data1[32];
int _colorOffset = 0;
DirMask _forwardMask = DIRMASK_N,
@@ -104,11 +108,6 @@ public:
Maps();
~Maps();
- /**
- * Load a map
- */
- void load(uint mapId);
-
/**
* Loads or saves map data
*/
Commit: e32d1a6f6ea6a826fc4ab9ecf46a07123cb20d8d
https://github.com/scummvm/scummvm/commit/e32d1a6f6ea6a826fc4ab9ecf46a07123cb20d8d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:34+01:00
Commit Message:
MM: MM1: Further saving code hookup
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/globals.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/mm1.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index f40e29998cb..c2d36044be4 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -49,12 +49,16 @@ void Events::runGame() {
_screen = new Graphics::Screen();
// Run the game
- // ***DEBUG*** start directly in-game
- for (uint i = 0; i < 6; ++i)
- g_globals->_party.push_back(g_globals->_roster[i]);
- g_globals->_maps.loadTown(Maps::SORPIGAL);
- msgGame(GameMessage("UPDATE"));
- //addView("Title");
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot == -1 ||
+ g_engine->loadGameState(saveSlot).getCode() != Common::kNoError) {
+ // ***DEBUG*** start directly in-game
+ for (uint i = 0; i < 6; ++i)
+ g_globals->_party.push_back(g_globals->_roster[i]);
+ g_globals->_maps.loadTown(Maps::SORPIGAL);
+ msgGame(GameMessage("UPDATE"));
+ //addView("Title");
+ }
Common::Event e;
for (;;) {
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 0184e0a2d71..12139cd7cf1 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -109,6 +109,7 @@ void Globals::synchronize(Common::Serializer &s) {
// Sync map data and visited tiles
_maps.synchronize(s);
+ _maps.synchronizeCurrent(s);
// Sync treasure data
_treasure.synchronize(s);
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 27f87e79e43..f123522e790 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -193,17 +193,32 @@ void Maps::load(uint mapId) {
}
void Maps::synchronize(Common::Serializer &s) {
- // Store a count of the number of maps,
- // just in case new ones are added in later
- uint8 mapCount = _maps.size();
+ // Store a count of the number of maps, just in case new ones
+ // are added in later as easter eggs just for ScummVM
+ int mapCount = _maps.size();
s.syncAsByte(mapCount);
- for (uint8 i = 0; i < mapCount; ++mapCount) {
+ for (int i = 0; i < mapCount; ++i) {
s.syncBytes(_maps[i]->_visited, MAP_SIZE);
}
}
+void Maps::synchronizeCurrent(Common::Serializer &s) {
+ // Save current map
+ s.syncAsUint16LE(_id);
+ s.syncAsByte(_section);
+
+ if (s.isLoading())
+ changeMap(_id, _section);
+
+ s.syncAsByte(_mapPos.x);
+ s.syncAsByte(_mapPos.y);
+}
+
void Maps::select(uint16 id, byte section) {
+ _id = id;
+ _section = section;
+
uint mapId = getIndex(id, section);
load(mapId);
}
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index d60df2608e2..23755d7015b 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -52,6 +52,8 @@ class Maps {
friend class Map;
private:
Common::Array<Map *> _maps;
+ uint16 _id = 0;
+ uint8 _section = 0;
private:
/**
* Gets the index of a map given the id values
@@ -113,6 +115,11 @@ public:
*/
void synchronize(Common::Serializer &s);
+ /**
+ * Loads or saves the current map info
+ */
+ void synchronizeCurrent(Common::Serializer &s);
+
/**
* Selects a map
*/
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 4213accea26..8fc72ebfd85 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -155,12 +155,13 @@ Common::Error MM1Engine::synchronizeSave(Common::Serializer &s) {
return Common::kReadingFailed;
s.setVersion(version);
- // Sync globals
- g_globals->synchronize(s);
-
// If we're loading a savegame, switch to the game view
- if (s.isLoading())
+ if (s.isLoading()) {
g_events->replaceView("Game", true);
+ }
+
+ // Sync globals
+ g_globals->synchronize(s);
return Common::kNoError;
}
Commit: 0713cbee6ef5d08f7de4dac809b8a9a7b3045468
https://github.com/scummvm/scummvm/commit/0713cbee6ef5d08f7de4dac809b8a9a7b3045468
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: Adding more data to savegames
Changed paths:
engines/mm/mm1/data/active_spells.cpp
engines/mm/mm1/data/active_spells.h
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/data/active_spells.cpp b/engines/mm/mm1/data/active_spells.cpp
index 74cb03a9dbf..4401bb88c0e 100644
--- a/engines/mm/mm1/data/active_spells.cpp
+++ b/engines/mm/mm1/data/active_spells.cpp
@@ -28,5 +28,9 @@ void ActiveSpells::clear() {
Common::fill(&_arr[0], &_arr[ACTIVE_SPELLS_COUNT], 0);
}
+void ActiveSpells::synchronize(Common::Serializer &s) {
+ s.syncBytes(_arr, ACTIVE_SPELLS_COUNT);
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/active_spells.h b/engines/mm/mm1/data/active_spells.h
index 56230c8a117..b72e563d737 100644
--- a/engines/mm/mm1/data/active_spells.h
+++ b/engines/mm/mm1/data/active_spells.h
@@ -55,7 +55,16 @@ union ActiveSpells {
byte _arr[ACTIVE_SPELLS_COUNT];
ActiveSpells() { clear(); }
+
+ /**
+ * Clear the spells
+ */
void clear();
+
+ /**
+ * Synchronize spell data to/from savegames
+ */
+ void synchronize(Common::Serializer &s);
};
} // namespace MM1
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index e9a57503a52..aee1b863a42 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -124,5 +124,15 @@ bool Party::checkPartyDead() const {
}
}
+void Party::synchronize(Common::Serializer &s) {
+ int partySize = size();
+ s.syncAsByte(partySize);
+ if (s.isLoading())
+ resize(partySize);
+
+ for (int i = 0; i < partySize; ++i)
+ (*this)[i].synchronize(s);
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index b46f6fff54f..ee5c9bdcc83 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -81,6 +81,11 @@ struct Party : public Common::Array<Character> {
* and if so, switches to the death screen
*/
bool checkPartyDead() const;
+
+ /**
+ * Synchronizes the party to/from savegames
+ */
+ void synchronize(Common::Serializer &s);
};
} // namespace MM1
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 12139cd7cf1..520411ad82f 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -111,10 +111,15 @@ void Globals::synchronize(Common::Serializer &s) {
_maps.synchronize(s);
_maps.synchronizeCurrent(s);
- // Sync treasure data
+ // Sync miscellaneous data
_treasure.synchronize(s);
+ _activeSpells.synchronize(s);
- _currCharacter = nullptr;
+ if (s.isLoading()) {
+ _currCharacter = nullptr;
+ _heardRumor = false;
+ _nonCombatEffectCtr = _combatEffectCtr = 0;
+ }
}
} // namespace MM1
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 0d49a45e070..999ac8f06a9 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -83,7 +83,7 @@ public:
}
/**
- * Saves or loads global data to/from savegames
+ * Saves global data to/from savegames
*/
void synchronize(Common::Serializer &s);
};
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index f123522e790..bb5137c5404 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -208,11 +208,19 @@ void Maps::synchronizeCurrent(Common::Serializer &s) {
s.syncAsUint16LE(_id);
s.syncAsByte(_section);
- if (s.isLoading())
- changeMap(_id, _section);
-
s.syncAsByte(_mapPos.x);
s.syncAsByte(_mapPos.y);
+ s.syncAsByte(_forwardMask);
+ s.syncAsByte(_backwardsMask);
+ s.syncAsByte(_leftMask);
+ s.syncAsByte(_rightMask);
+ s.syncAsSByte(_forwardOffset);
+ s.syncAsSByte(_backwardsOffset);
+ s.syncAsSByte(_leftOffset);
+ s.syncAsSByte(_rightOffset);
+
+ if (s.isLoading())
+ changeMap(_id, _section);
}
void Maps::select(uint16 id, byte section) {
Commit: 1bf898525f8879bccc7f4751eb613dc3b91bfed2
https://github.com/scummvm/scummvm/commit/1bf898525f8879bccc7f4751eb613dc3b91bfed2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: Added console command to list specials
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/maps/map.h
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 9ecadd88359..ee3bb2377cc 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -41,6 +41,7 @@ Console::Console() : GUI::Debugger() {
registerCmd("intangible", WRAP_METHOD(Console, cmdIntangible));
registerCmd("cast", WRAP_METHOD(Console, cmdCast));
registerCmd("encounter", WRAP_METHOD(Console, cmdEncounter));
+ registerCmd("specials", WRAP_METHOD(Console, cmdSpecials));
}
bool Console::cmdDumpMap(int argc, const char **argv) {
@@ -324,5 +325,33 @@ bool Console::cmdEncounter(int argc, const char **argv) {
return false;
}
+bool Console::cmdSpecials(int argc, const char **argv) {
+ int count = g_maps->_currentMap->dataByte(Maps::MAP_SPECIAL_COUNT);
+
+ for (int i = 0; i < count; ++i) {
+ int mapOffset = g_maps->_currentMap->dataByte(51 + i);
+ int x = mapOffset % MAP_W;
+ int y = mapOffset / MAP_W;
+ Common::String line = Common::String::format(
+ "Special #%.2d - %d, %d (", i, x, y);
+
+ int dirMask = g_maps->_currentMap->dataByte(51 + i);
+ if (dirMask & Maps::DIRMASK_N)
+ line += "N,";
+ if (dirMask & Maps::DIRMASK_S)
+ line += "S,";
+ if (dirMask & Maps::DIRMASK_E)
+ line += "E,";
+ if (dirMask & Maps::DIRMASK_W)
+ line += "W,";
+
+ line.deleteLastChar();
+ line += ')';
+ debugPrintf("%s\n", line.c_str());
+ }
+
+ return true;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index 115b37b9fb6..83444fb36ad 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -75,6 +75,11 @@ protected:
*/
bool cmdEncounter(int argc, const char **argv);
+ /**
+ * List the special cells in the current map
+ */
+ bool cmdSpecials(int argc, const char **argv);
+
public:
Console();
~Console() override {}
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index d40e54a6381..161de883b50 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -81,7 +81,8 @@ enum DataOffset {
MAP_FLAGS = 46,
MAP_47 = 47,
MAP_TRAP_THRESHOLD = 48,
- MAP_49 = 49
+ MAP_49 = 49,
+ MAP_SPECIAL_COUNT = 50
};
enum WallType {
Commit: 299687eb729b56c9405e500ede7e6f9a70a2ad52
https://github.com/scummvm/scummvm/commit/299687eb729b56c9405e500ede7e6f9a70a2ad52
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: specials console cmd now includes codeless specials
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/game/view_base.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index ee3bb2377cc..fd9332f17b6 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -327,26 +327,46 @@ bool Console::cmdEncounter(int argc, const char **argv) {
bool Console::cmdSpecials(int argc, const char **argv) {
int count = g_maps->_currentMap->dataByte(Maps::MAP_SPECIAL_COUNT);
-
- for (int i = 0; i < count; ++i) {
- int mapOffset = g_maps->_currentMap->dataByte(51 + i);
- int x = mapOffset % MAP_W;
- int y = mapOffset / MAP_W;
+ int i, mapOffset;
+
+ for (int mapPos = 0; mapPos < (MAP_W * MAP_H); ++mapPos) {
+ // Check whether the map cell is flagged as special, and whether
+ // the cell, if special, has special handling code
+ bool isSpecial = (g_maps->_currentMap->_states[mapPos]
+ & Maps::CELL_SPECIAL) != 0;
+
+ for (i = 0; i < count; ++i) {
+ mapOffset = g_maps->_currentMap->dataByte(51 + i);
+ if (mapOffset == mapPos)
+ break;
+ }
+ bool isExtraSpecial = i < count;
+ if (!isSpecial && !isExtraSpecial)
+ continue;
+
+ int x = mapPos % MAP_W;
+ int y = mapPos / MAP_W;
+ Common::String specialIdx = !isExtraSpecial ? "--" :
+ Common::String::format("%.2d", i);
Common::String line = Common::String::format(
- "Special #%.2d - %d, %d (", i, x, y);
-
- int dirMask = g_maps->_currentMap->dataByte(51 + i);
- if (dirMask & Maps::DIRMASK_N)
- line += "N,";
- if (dirMask & Maps::DIRMASK_S)
- line += "S,";
- if (dirMask & Maps::DIRMASK_E)
- line += "E,";
- if (dirMask & Maps::DIRMASK_W)
- line += "W,";
-
- line.deleteLastChar();
- line += ')';
+ "Special #%s - %d, %d", specialIdx.c_str(), x, y);
+
+ if (isExtraSpecial) {
+ line += " (";
+ int dirMask = g_maps->_currentMap->dataByte(51 + count + i);
+ if (dirMask & Maps::DIRMASK_N)
+ line += "N,";
+ if (dirMask & Maps::DIRMASK_S)
+ line += "S,";
+ if (dirMask & Maps::DIRMASK_E)
+ line += "E,";
+ if (dirMask & Maps::DIRMASK_W)
+ line += "W,";
+
+ line.deleteLastChar();
+ line += ')';
+ }
+
debugPrintf("%s\n", line.c_str());
}
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index ba71abfd76c..c87cebb7243 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -57,7 +57,7 @@ darkness:
// Encounter checks
g_globals->_encounters._encounterType = NORMAL_SURPRISED;
- if (maps._currentState & 0x80) {
+ if (maps._currentState & Maps::CELL_SPECIAL) {
map.special();
} else if (_stepRandom) {
Commit: 3714770314064fe373eaaa5658a5494bd239fef1
https://github.com/scummvm/scummvm/commit/3714770314064fe373eaaa5658a5494bd239fef1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: Yet more changes to specials console command
This latest version keeps the code-associated specials
in order, and lists special map cells that are codeless
at the end of the list
Changed paths:
engines/mm/mm1/console.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index fd9332f17b6..71b57ed4720 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -327,47 +327,53 @@ bool Console::cmdEncounter(int argc, const char **argv) {
bool Console::cmdSpecials(int argc, const char **argv) {
int count = g_maps->_currentMap->dataByte(Maps::MAP_SPECIAL_COUNT);
- int i, mapOffset;
+ // List specials that have code attached
+ for (int i = 0; i < count; ++i) {
+ int mapOffset = g_maps->_currentMap->dataByte(51 + i);
+ int x = mapOffset % MAP_W;
+ int y = mapOffset / MAP_W;
+ Common::String line = Common::String::format(
+ "Special #%.2d - %d, %d (", i, x, y);
+
+ int dirMask = g_maps->_currentMap->dataByte(51 + i);
+ if (dirMask & Maps::DIRMASK_N)
+ line += "N,";
+ if (dirMask & Maps::DIRMASK_S)
+ line += "S,";
+ if (dirMask & Maps::DIRMASK_E)
+ line += "E,";
+ if (dirMask & Maps::DIRMASK_W)
+ line += "W,";
+
+ line.deleteLastChar();
+ line += ')';
+ debugPrintf("%s\n", line.c_str());
+ }
+
+ // Iterate through the map to find special cells that are codeless
+ int mapOffset = 0, i;
for (int mapPos = 0; mapPos < (MAP_W * MAP_H); ++mapPos) {
- // Check whether the map cell is flagged as special, and whether
- // the cell, if special, has special handling code
bool isSpecial = (g_maps->_currentMap->_states[mapPos]
& Maps::CELL_SPECIAL) != 0;
+ if (!isSpecial)
+ continue;
+
+ int x = mapPos % MAP_W;
+ int y = mapPos / MAP_W;
for (i = 0; i < count; ++i) {
mapOffset = g_maps->_currentMap->dataByte(51 + i);
if (mapOffset == mapPos)
break;
}
- bool isExtraSpecial = i < count;
- if (!isSpecial && !isExtraSpecial)
- continue;
- int x = mapPos % MAP_W;
- int y = mapPos / MAP_W;
- Common::String specialIdx = !isExtraSpecial ? "--" :
- Common::String::format("%.2d", i);
- Common::String line = Common::String::format(
- "Special #%s - %d, %d", specialIdx.c_str(), x, y);
-
- if (isExtraSpecial) {
- line += " (";
- int dirMask = g_maps->_currentMap->dataByte(51 + count + i);
- if (dirMask & Maps::DIRMASK_N)
- line += "N,";
- if (dirMask & Maps::DIRMASK_S)
- line += "S,";
- if (dirMask & Maps::DIRMASK_E)
- line += "E,";
- if (dirMask & Maps::DIRMASK_W)
- line += "W,";
-
- line.deleteLastChar();
- line += ')';
+ // Add row for special if there's no code handling
+ if (i == count) {
+ Common::String line = Common::String::format(
+ "Special #-- - %d, %d", x, y);
+ debugPrintf("%s\n", line.c_str());
}
-
- debugPrintf("%s\n", line.c_str());
}
return true;
Commit: 8922bb134e0f87bb4d819365857e7ee884ace66d
https://github.com/scummvm/scummvm/commit/8922bb134e0f87bb4d819365857e7ee884ace66d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: Added encounters console command to toggle encounters on/off
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/globals.h
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 71b57ed4720..ba3ec3bef72 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -41,6 +41,7 @@ Console::Console() : GUI::Debugger() {
registerCmd("intangible", WRAP_METHOD(Console, cmdIntangible));
registerCmd("cast", WRAP_METHOD(Console, cmdCast));
registerCmd("encounter", WRAP_METHOD(Console, cmdEncounter));
+ registerCmd("encounters", WRAP_METHOD(Console, cmdEncounters));
registerCmd("specials", WRAP_METHOD(Console, cmdSpecials));
}
@@ -325,6 +326,18 @@ bool Console::cmdEncounter(int argc, const char **argv) {
return false;
}
+bool Console::cmdEncounters(int argc, const char **argv) {
+ if (argc == 1) {
+ g_globals->_encountersOn = !g_globals->_encountersOn;
+ } else {
+ g_globals->_encountersOn = !scumm_stricmp(argv[1], "on");
+ }
+
+ debugPrintf("Encounters are %s\n",
+ g_globals->_encountersOn ? "on" : "off");
+ return true;
+}
+
bool Console::cmdSpecials(int argc, const char **argv) {
int count = g_maps->_currentMap->dataByte(Maps::MAP_SPECIAL_COUNT);
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index 83444fb36ad..7d095ae5887 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -75,6 +75,11 @@ protected:
*/
bool cmdEncounter(int argc, const char **argv);
+ /**
+ * Turns encounters on or off
+ */
+ bool cmdEncounters(int argc, const char **argv);
+
/**
* List the special cells in the current map
*/
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index be3250c28e6..eea600275b7 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -31,6 +31,9 @@ namespace MM1 {
namespace Game {
void Encounter::execute() {
+ if (!g_globals->_encountersOn)
+ return;
+
Maps::Map &map = *g_maps->_currentMap;
int comp, maxRand, maxVal;
const Monster *monsterP;
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 999ac8f06a9..fa4ee88f00b 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -48,7 +48,6 @@ public:
ItemsArray _items;
Maps::TownId _startingTown = Maps::SORPIGAL;
Maps::Maps _maps;
- bool _intangible = false; // Console flag
BitmapFont _font;
bool _heardRumor = false;
Game::Encounter _encounters;
@@ -56,6 +55,11 @@ public:
Treasure _treasure;
byte _delay = 5;
int _nonCombatEffectCtr = 0, _combatEffectCtr = 0;
+
+ // Console flags
+ bool _intangible = false;
+ bool _encountersOn = true;
+
public:
// Enhanced mode globals
Xeen::SpriteResource _mainIcons;
Commit: e4a2d7e78240cecd5b58d81e93ce539924017e61
https://github.com/scummvm/scummvm/commit/e4a2d7e78240cecd5b58d81e93ce539924017e61
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: Add spells state info to savegames
Changed paths:
engines/mm/mm1/data/spells_state.h
engines/mm/mm1/globals.cpp
diff --git a/engines/mm/mm1/data/spells_state.h b/engines/mm/mm1/data/spells_state.h
index b1ed76bcbc7..22c3871f80d 100644
--- a/engines/mm/mm1/data/spells_state.h
+++ b/engines/mm/mm1/data/spells_state.h
@@ -22,6 +22,7 @@
#ifndef MM1_DATA_SPELLS_H
#define MM1_DATA_SPELLS_H
+#include "common/serializer.h"
#include "mm/mm1/data/character.h"
namespace MM {
@@ -33,6 +34,18 @@ struct SpellsState {
int _mmVal7 = 0;
Resistance _resistanceType = RESISTANCE_MAGIC;
byte _newCondition = 0;
+
+ /**
+ * Synchronize data to/from savegames
+ */
+ void synchronize(Common::Serializer &s) {
+ s.syncAsByte(_mmVal1);
+ s.syncAsByte(_mmVal2);
+ s.syncAsByte(_mmVal5);
+ s.syncAsByte(_mmVal7);
+ s.syncAsByte(_resistanceType);
+ s.syncAsByte(_newCondition);
+ }
};
} // namespace MM1
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 520411ad82f..01e5abbda1f 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -98,23 +98,16 @@ bool Globals::load(bool isEnhanced) {
void Globals::synchronize(Common::Serializer &s) {
s.syncAsByte(_startingTown);
- // Sync the party
- int partySize = _party.size();
- s.syncAsByte(partySize);
- if (s.isLoading())
- _party.resize(partySize);
-
- for (int i = 0; i < partySize; ++i)
- _party[i].synchronize(s);
+ // Sync the state information
+ _party.synchronize(s);
+ _activeSpells.synchronize(s);
+ _spellsState.synchronize(s);
+ _treasure.synchronize(s);
// Sync map data and visited tiles
_maps.synchronize(s);
_maps.synchronizeCurrent(s);
- // Sync miscellaneous data
- _treasure.synchronize(s);
- _activeSpells.synchronize(s);
-
if (s.isLoading()) {
_currCharacter = nullptr;
_heardRumor = false;
Commit: d2dc840175e485b51d9f9d3e542e0df2f0889658
https://github.com/scummvm/scummvm/commit/d2dc840175e485b51d9f9d3e542e0df2f0889658
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: Changed Spells to SpellsParty
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
engines/mm/mm1/views/character_info.cpp
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index ba3ec3bef72..3a452d47a6c 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -309,7 +309,7 @@ bool Console::cmdCast(int argc, const char **argv) {
int spellIndex = getSpellIndex(c, strToInt(argv[1]), strToInt(argv[2]));
setSpell(spellIndex, 0, 0);
- Game::Spells::cast(_spellIndex, c);
+ Game::SpellsParty::cast(_spellIndex, c);
return false;
}
}
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 2c142fa8faa..a8da6be7e2a 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -34,7 +34,7 @@ namespace MM {
namespace MM1 {
namespace Game {
-Spells::SpellFn Spells::SPELLS[SPELLS_COUNT] = {
+SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
// Cleric spells
placeholder,
placeholder,
@@ -161,12 +161,12 @@ byte FLY_MAP_Y[20] = {
14, 15, 15, 7, 15
};
-SpellResult Spells::cast(int spell, Character *chr) {
+SpellResult SpellsParty::cast(int spell, Character *chr) {
assert(spell < SPELLS_COUNT);
return SPELLS[spell](chr);
}
-SpellResult Spells::cleric11_awaken(Character *chr) {
+SpellResult SpellsParty::cleric11_awaken(Character *chr) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
if (!(c._condition & BAD_CONDITION))
@@ -176,12 +176,12 @@ SpellResult Spells::cleric11_awaken(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric12_bless(Character *chr) {
+SpellResult SpellsParty::cleric12_bless(Character *chr) {
g_globals->_activeSpells._s.bless++;
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric13_blind(Character *chr) {
+SpellResult SpellsParty::cleric13_blind(Character *chr) {
SpellsState &s = g_globals->_spellsState;
s._mmVal1++;
s._mmVal2 = 7;
@@ -192,17 +192,17 @@ SpellResult Spells::cleric13_blind(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric14_firstAid(Character *chr) {
+SpellResult SpellsParty::cleric14_firstAid(Character *chr) {
restoreHp(chr, 8);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric15_light(Character *chr) {
+SpellResult SpellsParty::cleric15_light(Character *chr) {
addLight(1);
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::cleric16_powerCure(Character *chr) {
+SpellResult SpellsParty::cleric16_powerCure(Character *chr) {
int totalHp = 0;
for (uint i = 0; i < g_globals->_currCharacter->_level._current; ++i)
totalHp += g_engine->getRandomNumber(10);
@@ -211,36 +211,36 @@ SpellResult Spells::cleric16_powerCure(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric17_protectionFromFear(Character *chr) {
+SpellResult SpellsParty::cleric17_protectionFromFear(Character *chr) {
g_globals->_activeSpells._s.fear =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric21_cureWounds(Character *chr) {
+SpellResult SpellsParty::cleric21_cureWounds(Character *chr) {
restoreHp(chr, 16);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric24_protectionFromCold(Character *chr) {
+SpellResult SpellsParty::cleric24_protectionFromCold(Character *chr) {
g_globals->_activeSpells._s.cold =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric25_protectionFromIce(Character *chr) {
+SpellResult SpellsParty::cleric25_protectionFromIce(Character *chr) {
g_globals->_activeSpells._s.fire =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric26_protectionFromPoison(Character *chr) {
+SpellResult SpellsParty::cleric26_protectionFromPoison(Character *chr) {
g_globals->_activeSpells._s.poison =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric31_createFood(Character *chr) {
+SpellResult SpellsParty::cleric31_createFood(Character *chr) {
if (chr->_food == MAX_FOOD) {
return SR_FAILED;
} else {
@@ -249,7 +249,7 @@ SpellResult Spells::cleric31_createFood(Character *chr) {
}
}
-SpellResult Spells::cleric32_cureBlindness(Character *chr) {
+SpellResult SpellsParty::cleric32_cureBlindness(Character *chr) {
if (chr->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
@@ -258,7 +258,7 @@ SpellResult Spells::cleric32_cureBlindness(Character *chr) {
}
}
-SpellResult Spells::cleric33_cureParalysis(Character *chr) {
+SpellResult SpellsParty::cleric33_cureParalysis(Character *chr) {
if (chr->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
@@ -267,24 +267,24 @@ SpellResult Spells::cleric33_cureParalysis(Character *chr) {
}
}
-SpellResult Spells::cleric34_lastingLight(Character *chr) {
+SpellResult SpellsParty::cleric34_lastingLight(Character *chr) {
addLight(19);
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::cleric37_removeQuest(Character *chr) {
+SpellResult SpellsParty::cleric37_removeQuest(Character *chr) {
for (uint i = 0; i < g_globals->_party.size(); ++i)
g_globals->_party[i]._quest = 0;
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric38_walkOnWater(Character *chr) {
+SpellResult SpellsParty::cleric38_walkOnWater(Character *chr) {
g_globals->_activeSpells._s.walk_on_water = MIN(
(int)g_globals->_activeSpells._s.walk_on_water + 1, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric41_cureDisease(Character *chr) {
+SpellResult SpellsParty::cleric41_cureDisease(Character *chr) {
if (chr->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
@@ -293,7 +293,7 @@ SpellResult Spells::cleric41_cureDisease(Character *chr) {
}
}
-SpellResult Spells::cleric42_neutralizePoison(Character *chr) {
+SpellResult SpellsParty::cleric42_neutralizePoison(Character *chr) {
if (chr->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
@@ -302,24 +302,24 @@ SpellResult Spells::cleric42_neutralizePoison(Character *chr) {
}
}
-SpellResult Spells::cleric43_protectionFromAcid(Character *chr) {
+SpellResult SpellsParty::cleric43_protectionFromAcid(Character *chr) {
g_globals->_activeSpells._s.acid =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric44_protectionFromElectricity(Character *chr) {
+SpellResult SpellsParty::cleric44_protectionFromElectricity(Character *chr) {
g_globals->_activeSpells._s.electricity =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric45_restoreAlignment(Character *chr) {
+SpellResult SpellsParty::cleric45_restoreAlignment(Character *chr) {
chr->_alignment = chr->_alignmentInitial;
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric48_surface(Character *chr) {
+SpellResult SpellsParty::cleric48_surface(Character *chr) {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
if (map[Maps::MAP_FLAGS] & 4) {
@@ -334,7 +334,7 @@ SpellResult Spells::cleric48_surface(Character *chr) {
}
}
-SpellResult Spells::cleric52_dispelMagic(Character *chr) {
+SpellResult SpellsParty::cleric52_dispelMagic(Character *chr) {
Maps::Map &map = *g_maps->_currentMap;
if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DISPEL_THRESHOLD]) {
Common::fill(&g_globals->_activeSpells._arr[0],
@@ -354,7 +354,7 @@ SpellResult Spells::cleric52_dispelMagic(Character *chr) {
}
}
-SpellResult Spells::cleric54_removeCondition(Character *chr) {
+SpellResult SpellsParty::cleric54_removeCondition(Character *chr) {
if (chr->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
@@ -368,7 +368,7 @@ SpellResult Spells::cleric54_removeCondition(Character *chr) {
}
}
-SpellResult Spells::cleric55_restoreEnergy(Character *chr) {
+SpellResult SpellsParty::cleric55_restoreEnergy(Character *chr) {
if (chr->_level._current < chr->_level._base) {
chr->_level._current = MIN(
chr->_level._current + g_engine->getRandomNumber(5),
@@ -380,7 +380,7 @@ SpellResult Spells::cleric55_restoreEnergy(Character *chr) {
}
}
-SpellResult Spells::cleric62_raiseDead(Character *chr) {
+SpellResult SpellsParty::cleric62_raiseDead(Character *chr) {
if ((chr->_condition == ERADICATED) ||
(chr->_condition & (BAD_CONDITION | DEAD)) ==
(BAD_CONDITION | DEAD))
@@ -403,7 +403,7 @@ SpellResult Spells::cleric62_raiseDead(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric63_rejuvinate(Character *chr) {
+SpellResult SpellsParty::cleric63_rejuvinate(Character *chr) {
if (g_engine->getRandomNumber(100) < 75) {
chr->_age._base = MIN(chr->_age._base - g_engine->getRandomNumber(10),
200);
@@ -415,7 +415,7 @@ SpellResult Spells::cleric63_rejuvinate(Character *chr) {
}
}
-SpellResult Spells::cleric64_stoneToFlesh(Character *chr) {
+SpellResult SpellsParty::cleric64_stoneToFlesh(Character *chr) {
if ((chr->_condition == ERADICATED) ||
(chr->_condition & (BAD_CONDITION | DEAD)) ==
(BAD_CONDITION | DEAD))
@@ -430,7 +430,7 @@ SpellResult Spells::cleric64_stoneToFlesh(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric65_townPortal(Character *chr) {
+SpellResult SpellsParty::cleric65_townPortal(Character *chr) {
Sound::sound(SOUND_2);
InfoMessage msg(
STRING["spells.which_town"],
@@ -468,7 +468,7 @@ SpellResult Spells::cleric65_townPortal(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::cleric73_protectionFromElements(Character *chr) {
+SpellResult SpellsParty::cleric73_protectionFromElements(Character *chr) {
int amount = g_globals->_currCharacter->_level._current + 25;
for (int i = 0; i < 6; ++i)
@@ -477,7 +477,7 @@ SpellResult Spells::cleric73_protectionFromElements(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult Spells::cleric74_resurrection(Character *chr) {
+SpellResult SpellsParty::cleric74_resurrection(Character *chr) {
if (chr->_condition == ERADICATED)
return SR_FAILED;
@@ -494,22 +494,22 @@ SpellResult Spells::cleric74_resurrection(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult Spells::wizard12_detectMagic(Character *chr) {
+SpellResult SpellsParty::wizard12_detectMagic(Character *chr) {
Views::Spells::DetectMagic::show();
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard15_leatherSkin(Character *chr) {
+SpellResult SpellsParty::wizard15_leatherSkin(Character *chr) {
g_globals->_activeSpells._s.leather_skin = g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult Spells::wizard17_location(Character *chr) {
+SpellResult SpellsParty::wizard17_location(Character *chr) {
Views::Spells::Location::show();
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard24_jump(Character *chr) {
+SpellResult SpellsParty::wizard24_jump(Character *chr) {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
@@ -542,13 +542,13 @@ SpellResult Spells::wizard24_jump(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard25_levitate(Character *chr) {
+SpellResult SpellsParty::wizard25_levitate(Character *chr) {
g_globals->_activeSpells._s.levitate =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult Spells::wizard32_fly(Character *chr) {
+SpellResult SpellsParty::wizard32_fly(Character *chr) {
Views::Spells::Fly::show(
[](int mapIndex) {
if (mapIndex != -1) {
@@ -565,19 +565,19 @@ SpellResult Spells::wizard32_fly(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard45_guardDog(Character *chr) {
+SpellResult SpellsParty::wizard45_guardDog(Character *chr) {
g_globals->_activeSpells._s.guard_dog =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult Spells::wizard46_psychicProtection(Character *chr) {
+SpellResult SpellsParty::wizard46_psychicProtection(Character *chr) {
g_globals->_activeSpells._s.psychic_protection =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult Spells::wizard54_shelter(Character *chr) {
+SpellResult SpellsParty::wizard54_shelter(Character *chr) {
if (g_maps->_currentState & 8)
return SR_FAILED;
@@ -585,12 +585,12 @@ SpellResult Spells::wizard54_shelter(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard55_teleport(Character *chr) {
+SpellResult SpellsParty::wizard55_teleport(Character *chr) {
Views::Spells::Teleport::show();
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard63_etherialize(Character *chr) {
+SpellResult SpellsParty::wizard63_etherialize(Character *chr) {
g_events->draw();
g_maps->_currentState = 0;
g_maps->step(Common::Point(1, 0));
@@ -598,17 +598,17 @@ SpellResult Spells::wizard63_etherialize(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard64_protectionFromMagic(Character *chr) {
+SpellResult SpellsParty::wizard64_protectionFromMagic(Character *chr) {
g_globals->_activeSpells._s.magic =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult Spells::wizard65_rechargeItem(Character *chr) {
+SpellResult SpellsParty::wizard65_rechargeItem(Character *chr) {
return SR_FAILED;
}
-SpellResult Spells::wizard71_astralSpell(Character *chr) {
+SpellResult SpellsParty::wizard71_astralSpell(Character *chr) {
Maps::Maps &maps = *g_maps;
maps._mapPos.x = 7;
maps._mapPos.y = 0;
@@ -617,20 +617,20 @@ SpellResult Spells::wizard71_astralSpell(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult Spells::wizard72_duplication(Character *chr) {
+SpellResult SpellsParty::wizard72_duplication(Character *chr) {
return SR_FAILED;
}
-void Spells::restoreHp(Character *chr, uint16 hp) {
+void SpellsParty::restoreHp(Character *chr, uint16 hp) {
chr->_hpBase = MIN((int)(chr->_hpBase + hp), (int)chr->_hpMax);
}
-void Spells::addLight(int amount) {
+void SpellsParty::addLight(int amount) {
g_globals->_activeSpells._s.light = MIN((int)g_globals->_activeSpells._s.light + amount, 255);
g_events->send("Game", GameMessage("UPDATE"));
}
-void Spells::iterateMonsters() {
+void SpellsParty::iterateMonsters() {
}
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 5a66e1dcecd..41c546c95a1 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -39,7 +39,7 @@ extern byte FLY_MAP_ID2[20];
extern byte FLY_MAP_X[20];
extern byte FLY_MAP_Y[20];
-class Spells {
+class SpellsParty {
typedef SpellResult(*SpellFn)(Character *chr);
private:
/**
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index f322c963679..57f76fab9c8 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -586,7 +586,7 @@ void CharacterInfo::combatUseItem(Inventory &inv, Inventory::Entry &invEntry, bo
if (item->_effectId == 0xff) {
setSpell(item->_spellId, 0, 0);
- Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
+ Game::SpellsParty::cast(_spellIndex, g_globals->_currCharacter);
} else {
// TODO: find out area of Character _effectId is used as an offset for
@@ -631,7 +631,7 @@ void CharacterInfo::nonCombatUseItem(Inventory &inv, Inventory::Entry &invEntry,
if (item->_effectId == 0xff) {
setSpell(item->_spellId, 0, 0);
- Game::Spells::cast(_spellIndex, g_globals->_currCharacter);
+ Game::SpellsParty::cast(_spellIndex, g_globals->_currCharacter);
} else {
// TODO: find out area of Character _effectId is used as an offset for
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index a4ea075e984..7a577f7742a 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -193,7 +193,7 @@ void CastSpell::performSpell(Character *chr) {
spellDone(STRING["dialogs.misc.magic_doesnt_work"], 5);
} else {
// Cast the spell
- switch (Game::Spells::cast(_spellIndex, chr)) {
+ switch (Game::SpellsParty::cast(_spellIndex, chr)) {
case Game::SR_FAILED:
// Spell failed
spellFailed();
Commit: 5c90a590b742c87d7ea3d0e53dbec749c669aae1
https://github.com/scummvm/scummvm/commit/5c90a590b742c87d7ea3d0e53dbec749c669aae1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:35+01:00
Commit Message:
MM: MM1: Set up SpellsParty so a dest monster can be specified
Changed paths:
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index a8da6be7e2a..8b67f519ce0 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -34,6 +34,9 @@ namespace MM {
namespace MM1 {
namespace Game {
+Character *SpellsParty::_destChar;
+int SpellsParty::_destMonsterNum;
+
SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
// Cleric spells
placeholder,
@@ -161,12 +164,27 @@ byte FLY_MAP_Y[20] = {
14, 15, 15, 7, 15
};
-SpellResult SpellsParty::cast(int spell, Character *chr) {
+SpellResult SpellsParty::cast(uint spell, Character *destChar) {
+ assert(spell < SPELLS_COUNT);
+ _destChar = destChar;
+ _destMonsterNum = -1;
+
+ return SPELLS[spell]();
+}
+
+SpellResult SpellsParty::cast(uint spell, int destMonsterIdx) {
assert(spell < SPELLS_COUNT);
- return SPELLS[spell](chr);
+ _destChar = nullptr;
+ _destMonsterNum = destMonsterIdx;
+
+ return SPELLS[spell]();
}
-SpellResult SpellsParty::cleric11_awaken(Character *chr) {
+bool SpellsParty::isInCombat() {
+ return g_events->isPresent("Combat");
+}
+
+SpellResult SpellsParty::cleric11_awaken() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
if (!(c._condition & BAD_CONDITION))
@@ -176,150 +194,150 @@ SpellResult SpellsParty::cleric11_awaken(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric12_bless(Character *chr) {
+SpellResult SpellsParty::cleric12_bless() {
g_globals->_activeSpells._s.bless++;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric13_blind(Character *chr) {
+SpellResult SpellsParty::cleric13_blind() {
SpellsState &s = g_globals->_spellsState;
s._mmVal1++;
s._mmVal2 = 7;
s._newCondition = BLINDED;
s._resistanceType = static_cast<Resistance>((int)s._resistanceType + 1);
- iterateMonsters();
+ iterateMonsters1();
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric14_firstAid(Character *chr) {
- restoreHp(chr, 8);
+SpellResult SpellsParty::cleric14_firstAid() {
+ restoreHp(_destChar, 8);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric15_light(Character *chr) {
+SpellResult SpellsParty::cleric15_light() {
addLight(1);
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::cleric16_powerCure(Character *chr) {
+SpellResult SpellsParty::cleric16_powerCure() {
int totalHp = 0;
for (uint i = 0; i < g_globals->_currCharacter->_level._current; ++i)
totalHp += g_engine->getRandomNumber(10);
- restoreHp(chr, MIN(totalHp, 250));
+ restoreHp(_destChar, MIN(totalHp, 250));
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric17_protectionFromFear(Character *chr) {
+SpellResult SpellsParty::cleric17_protectionFromFear() {
g_globals->_activeSpells._s.fear =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric21_cureWounds(Character *chr) {
- restoreHp(chr, 16);
+SpellResult SpellsParty::cleric21_cureWounds() {
+ restoreHp(_destChar, 16);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric24_protectionFromCold(Character *chr) {
+SpellResult SpellsParty::cleric24_protectionFromCold() {
g_globals->_activeSpells._s.cold =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric25_protectionFromIce(Character *chr) {
+SpellResult SpellsParty::cleric25_protectionFromIce() {
g_globals->_activeSpells._s.fire =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric26_protectionFromPoison(Character *chr) {
+SpellResult SpellsParty::cleric26_protectionFromPoison() {
g_globals->_activeSpells._s.poison =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric31_createFood(Character *chr) {
- if (chr->_food == MAX_FOOD) {
+SpellResult SpellsParty::cleric31_createFood() {
+ if (_destChar->_food == MAX_FOOD) {
return SR_FAILED;
} else {
- chr->_food = MIN(chr->_food + 6, MAX_FOOD);
+ _destChar->_food = MIN(_destChar->_food + 6, MAX_FOOD);
return SR_SUCCESS_DONE;
}
}
-SpellResult SpellsParty::cleric32_cureBlindness(Character *chr) {
- if (chr->_condition & BAD_CONDITION) {
+SpellResult SpellsParty::cleric32_cureBlindness() {
+ if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
- chr->_condition &= ~BLINDED;
+ _destChar->_condition &= ~BLINDED;
return SR_SUCCESS_DONE;
}
}
-SpellResult SpellsParty::cleric33_cureParalysis(Character *chr) {
- if (chr->_condition & BAD_CONDITION) {
+SpellResult SpellsParty::cleric33_cureParalysis() {
+ if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
- chr->_condition &= ~PARALYZED;
+ _destChar->_condition &= ~PARALYZED;
return SR_SUCCESS_DONE;
}
}
-SpellResult SpellsParty::cleric34_lastingLight(Character *chr) {
+SpellResult SpellsParty::cleric34_lastingLight() {
addLight(19);
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::cleric37_removeQuest(Character *chr) {
+SpellResult SpellsParty::cleric37_removeQuest() {
for (uint i = 0; i < g_globals->_party.size(); ++i)
g_globals->_party[i]._quest = 0;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric38_walkOnWater(Character *chr) {
+SpellResult SpellsParty::cleric38_walkOnWater() {
g_globals->_activeSpells._s.walk_on_water = MIN(
(int)g_globals->_activeSpells._s.walk_on_water + 1, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric41_cureDisease(Character *chr) {
- if (chr->_condition & BAD_CONDITION) {
+SpellResult SpellsParty::cleric41_cureDisease() {
+ if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
- chr->_condition &= ~DISEASED;
+ _destChar->_condition &= ~DISEASED;
return SR_SUCCESS_DONE;
}
}
-SpellResult SpellsParty::cleric42_neutralizePoison(Character *chr) {
- if (chr->_condition & BAD_CONDITION) {
+SpellResult SpellsParty::cleric42_neutralizePoison() {
+ if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
- chr->_condition &= ~POISONED;
+ _destChar->_condition &= ~POISONED;
return SR_SUCCESS_DONE;
}
}
-SpellResult SpellsParty::cleric43_protectionFromAcid(Character *chr) {
+SpellResult SpellsParty::cleric43_protectionFromAcid() {
g_globals->_activeSpells._s.acid =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric44_protectionFromElectricity(Character *chr) {
+SpellResult SpellsParty::cleric44_protectionFromElectricity() {
g_globals->_activeSpells._s.electricity =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric45_restoreAlignment(Character *chr) {
- chr->_alignment = chr->_alignmentInitial;
+SpellResult SpellsParty::cleric45_restoreAlignment() {
+ _destChar->_alignment = _destChar->_alignmentInitial;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric48_surface(Character *chr) {
+SpellResult SpellsParty::cleric48_surface() {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
if (map[Maps::MAP_FLAGS] & 4) {
@@ -334,7 +352,7 @@ SpellResult SpellsParty::cleric48_surface(Character *chr) {
}
}
-SpellResult SpellsParty::cleric52_dispelMagic(Character *chr) {
+SpellResult SpellsParty::cleric52_dispelMagic() {
Maps::Map &map = *g_maps->_currentMap;
if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DISPEL_THRESHOLD]) {
Common::fill(&g_globals->_activeSpells._arr[0],
@@ -354,25 +372,25 @@ SpellResult SpellsParty::cleric52_dispelMagic(Character *chr) {
}
}
-SpellResult SpellsParty::cleric54_removeCondition(Character *chr) {
- if (chr->_condition & BAD_CONDITION) {
+SpellResult SpellsParty::cleric54_removeCondition() {
+ if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
- chr->_condition = FINE;
+ _destChar->_condition = FINE;
- if (!chr->_hpBase)
- chr->_hpBase = 1;
- restoreHp(chr, 1);
+ if (!_destChar->_hpBase)
+ _destChar->_hpBase = 1;
+ restoreHp(_destChar, 1);
return SR_SUCCESS_DONE;
}
}
-SpellResult SpellsParty::cleric55_restoreEnergy(Character *chr) {
- if (chr->_level._current < chr->_level._base) {
- chr->_level._current = MIN(
- chr->_level._current + g_engine->getRandomNumber(5),
- (int)chr->_level._base
+SpellResult SpellsParty::cleric55_restoreEnergy() {
+ if (_destChar->_level._current < _destChar->_level._base) {
+ _destChar->_level._current = MIN(
+ _destChar->_level._current + g_engine->getRandomNumber(5),
+ (int)_destChar->_level._base
);
return SR_SUCCESS_DONE;
} else {
@@ -380,9 +398,9 @@ SpellResult SpellsParty::cleric55_restoreEnergy(Character *chr) {
}
}
-SpellResult SpellsParty::cleric62_raiseDead(Character *chr) {
- if ((chr->_condition == ERADICATED) ||
- (chr->_condition & (BAD_CONDITION | DEAD)) ==
+SpellResult SpellsParty::cleric62_raiseDead() {
+ if ((_destChar->_condition == ERADICATED) ||
+ (_destChar->_condition & (BAD_CONDITION | DEAD)) ==
(BAD_CONDITION | DEAD))
return SR_FAILED;
int rnd = g_engine->getRandomNumber(100);
@@ -394,43 +412,43 @@ SpellResult SpellsParty::cleric62_raiseDead(Character *chr) {
return SR_FAILED;
}
- if (chr->_condition == (BAD_CONDITION | DEAD | STONE))
- chr->_condition = BAD_CONDITION | STONE;
+ if (_destChar->_condition == (BAD_CONDITION | DEAD | STONE))
+ _destChar->_condition = BAD_CONDITION | STONE;
else
- chr->_condition = FINE;
+ _destChar->_condition = FINE;
- chr->_hpBase = 1;
+ _destChar->_hpBase = 1;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric63_rejuvinate(Character *chr) {
+SpellResult SpellsParty::cleric63_rejuvinate() {
if (g_engine->getRandomNumber(100) < 75) {
- chr->_age._base = MIN(chr->_age._base - g_engine->getRandomNumber(10),
+ _destChar->_age._base = MIN(_destChar->_age._base - g_engine->getRandomNumber(10),
200);
return SR_FAILED;
} else {
// Failed, increase the user's age
- chr->_age._base = MIN(chr->_age._base + 10, 200);
+ _destChar->_age._base = MIN(_destChar->_age._base + 10, 200);
return SR_FAILED;
}
}
-SpellResult SpellsParty::cleric64_stoneToFlesh(Character *chr) {
- if ((chr->_condition == ERADICATED) ||
- (chr->_condition & (BAD_CONDITION | DEAD)) ==
+SpellResult SpellsParty::cleric64_stoneToFlesh() {
+ if ((_destChar->_condition == ERADICATED) ||
+ (_destChar->_condition & (BAD_CONDITION | DEAD)) ==
(BAD_CONDITION | DEAD))
return SR_FAILED;
- if (chr->_condition == (BAD_CONDITION | DEAD | STONE))
- chr->_condition = BAD_CONDITION | DEAD;
+ if (_destChar->_condition == (BAD_CONDITION | DEAD | STONE))
+ _destChar->_condition = BAD_CONDITION | DEAD;
else
- chr->_condition = FINE;
+ _destChar->_condition = FINE;
- chr->_hpBase = 1;
+ _destChar->_hpBase = 1;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric65_townPortal(Character *chr) {
+SpellResult SpellsParty::cleric65_townPortal() {
Sound::sound(SOUND_2);
InfoMessage msg(
STRING["spells.which_town"],
@@ -468,7 +486,7 @@ SpellResult SpellsParty::cleric65_townPortal(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::cleric73_protectionFromElements(Character *chr) {
+SpellResult SpellsParty::cleric73_protectionFromElements() {
int amount = g_globals->_currCharacter->_level._current + 25;
for (int i = 0; i < 6; ++i)
@@ -477,39 +495,39 @@ SpellResult SpellsParty::cleric73_protectionFromElements(Character *chr) {
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::cleric74_resurrection(Character *chr) {
- if (chr->_condition == ERADICATED)
+SpellResult SpellsParty::cleric74_resurrection() {
+ if (_destChar->_condition == ERADICATED)
return SR_FAILED;
- if (chr->_age._base < 10 || chr->_age._base > 200)
- chr->_age._base = 200;
+ if (_destChar->_age._base < 10 || _destChar->_age._base > 200)
+ _destChar->_age._base = 200;
if (g_engine->getRandomNumber(100) > 75)
return SR_FAILED;
- chr->_endurance._base = MAX((int)chr->_endurance._base - 1, 1);
- chr->_condition = FINE;
- restoreHp(chr, 1);
+ _destChar->_endurance._base = MAX((int)_destChar->_endurance._base - 1, 1);
+ _destChar->_condition = FINE;
+ restoreHp(_destChar, 1);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::wizard12_detectMagic(Character *chr) {
+SpellResult SpellsParty::wizard12_detectMagic() {
Views::Spells::DetectMagic::show();
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard15_leatherSkin(Character *chr) {
+SpellResult SpellsParty::wizard15_leatherSkin() {
g_globals->_activeSpells._s.leather_skin = g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::wizard17_location(Character *chr) {
+SpellResult SpellsParty::wizard17_location() {
Views::Spells::Location::show();
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard24_jump(Character *chr) {
+SpellResult SpellsParty::wizard24_jump() {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
@@ -542,13 +560,13 @@ SpellResult SpellsParty::wizard24_jump(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard25_levitate(Character *chr) {
+SpellResult SpellsParty::wizard25_levitate() {
g_globals->_activeSpells._s.levitate =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::wizard32_fly(Character *chr) {
+SpellResult SpellsParty::wizard32_fly() {
Views::Spells::Fly::show(
[](int mapIndex) {
if (mapIndex != -1) {
@@ -565,19 +583,19 @@ SpellResult SpellsParty::wizard32_fly(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard45_guardDog(Character *chr) {
+SpellResult SpellsParty::wizard45_guardDog() {
g_globals->_activeSpells._s.guard_dog =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::wizard46_psychicProtection(Character *chr) {
+SpellResult SpellsParty::wizard46_psychicProtection() {
g_globals->_activeSpells._s.psychic_protection =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::wizard54_shelter(Character *chr) {
+SpellResult SpellsParty::wizard54_shelter() {
if (g_maps->_currentState & 8)
return SR_FAILED;
@@ -585,12 +603,12 @@ SpellResult SpellsParty::wizard54_shelter(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard55_teleport(Character *chr) {
+SpellResult SpellsParty::wizard55_teleport() {
Views::Spells::Teleport::show();
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard63_etherialize(Character *chr) {
+SpellResult SpellsParty::wizard63_etherialize() {
g_events->draw();
g_maps->_currentState = 0;
g_maps->step(Common::Point(1, 0));
@@ -598,17 +616,17 @@ SpellResult SpellsParty::wizard63_etherialize(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard64_protectionFromMagic(Character *chr) {
+SpellResult SpellsParty::wizard64_protectionFromMagic() {
g_globals->_activeSpells._s.magic =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
-SpellResult SpellsParty::wizard65_rechargeItem(Character *chr) {
+SpellResult SpellsParty::wizard65_rechargeItem() {
return SR_FAILED;
}
-SpellResult SpellsParty::wizard71_astralSpell(Character *chr) {
+SpellResult SpellsParty::wizard71_astralSpell() {
Maps::Maps &maps = *g_maps;
maps._mapPos.x = 7;
maps._mapPos.y = 0;
@@ -617,12 +635,12 @@ SpellResult SpellsParty::wizard71_astralSpell(Character *chr) {
return SR_SUCCESS_SILENT;
}
-SpellResult SpellsParty::wizard72_duplication(Character *chr) {
+SpellResult SpellsParty::wizard72_duplication() {
return SR_FAILED;
}
-void SpellsParty::restoreHp(Character *chr, uint16 hp) {
- chr->_hpBase = MIN((int)(chr->_hpBase + hp), (int)chr->_hpMax);
+void SpellsParty::restoreHp(Character *destChar, uint16 hp) {
+ destChar->_hpBase = MIN((int)(_destChar->_hpBase + hp), (int)_destChar->_hpMax);
}
void SpellsParty::addLight(int amount) {
@@ -630,10 +648,14 @@ void SpellsParty::addLight(int amount) {
g_events->send("Game", GameMessage("UPDATE"));
}
-void SpellsParty::iterateMonsters() {
+void SpellsParty::iterateMonsters1() {
}
+void SpellsParty::iterateMonsters2() {
+
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 41c546c95a1..dba94f66dec 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -40,8 +40,16 @@ extern byte FLY_MAP_X[20];
extern byte FLY_MAP_Y[20];
class SpellsParty {
- typedef SpellResult(*SpellFn)(Character *chr);
+ typedef SpellResult(*SpellFn)();
private:
+ static Character *_destChar;
+ static int _destMonsterNum;
+private:
+ /**
+ * Returns true if in combat
+ */
+ static bool isInCombat();
+
/**
* Restores an amount of Hp
*/
@@ -52,75 +60,75 @@ private:
*/
static void addLight(int amount);
- static void iterateMonsters();
+ static void iterateMonsters1();
+ static void iterateMonsters2();
private:
- static SpellResult placeholder(Character *chr) {
+ static SpellResult placeholder() {
return SR_FAILED;
}
- static SpellResult cleric11_awaken(Character *chr);
- static SpellResult cleric12_bless(Character *chr);
- static SpellResult cleric13_blind(Character *chr);
- static SpellResult cleric14_firstAid(Character *chr);
- static SpellResult cleric15_light(Character *chr);
- static SpellResult cleric16_powerCure(Character *chr);
- static SpellResult cleric17_protectionFromFear(Character *chr);
- static SpellResult cleric21_cureWounds(Character *chr);
- static SpellResult cleric24_protectionFromCold(Character *chr);
- static SpellResult cleric25_protectionFromIce(Character *chr);
- static SpellResult cleric26_protectionFromPoison(Character *chr);
- static SpellResult cleric31_createFood(Character *chr);
- static SpellResult cleric32_cureBlindness(Character *chr);
- static SpellResult cleric33_cureParalysis(Character *chr);
- static SpellResult cleric34_lastingLight(Character *chr);
- static SpellResult cleric37_removeQuest(Character *chr);
- static SpellResult cleric38_walkOnWater(Character *chr);
- static SpellResult cleric41_cureDisease(Character *chr);
- static SpellResult cleric42_neutralizePoison(Character *chr);
- static SpellResult cleric43_protectionFromAcid(Character *chr);
- static SpellResult cleric44_protectionFromElectricity(Character *chr);
- static SpellResult cleric45_restoreAlignment(Character *chr);
- static SpellResult cleric48_surface(Character *chr);
- static SpellResult cleric52_dispelMagic(Character *chr);
- static SpellResult cleric54_removeCondition(Character *chr);
- static SpellResult cleric55_restoreEnergy(Character *chr);
- static SpellResult cleric62_raiseDead(Character *chr);
- static SpellResult cleric63_rejuvinate(Character *chr);
- static SpellResult cleric64_stoneToFlesh(Character *chr);
- static SpellResult cleric65_townPortal(Character *chr);
- static SpellResult cleric73_protectionFromElements(Character *chr);
- static SpellResult cleric74_resurrection(Character *chr);
+ static SpellResult cleric11_awaken();
+ static SpellResult cleric12_bless();
+ static SpellResult cleric13_blind();
+ static SpellResult cleric14_firstAid();
+ static SpellResult cleric15_light();
+ static SpellResult cleric16_powerCure();
+ static SpellResult cleric17_protectionFromFear();
+ static SpellResult cleric21_cureWounds();
+ static SpellResult cleric24_protectionFromCold();
+ static SpellResult cleric25_protectionFromIce();
+ static SpellResult cleric26_protectionFromPoison();
+ static SpellResult cleric31_createFood();
+ static SpellResult cleric32_cureBlindness();
+ static SpellResult cleric33_cureParalysis();
+ static SpellResult cleric34_lastingLight();
+ static SpellResult cleric37_removeQuest();
+ static SpellResult cleric38_walkOnWater();
+ static SpellResult cleric41_cureDisease();
+ static SpellResult cleric42_neutralizePoison();
+ static SpellResult cleric43_protectionFromAcid();
+ static SpellResult cleric44_protectionFromElectricity();
+ static SpellResult cleric45_restoreAlignment();
+ static SpellResult cleric48_surface();
+ static SpellResult cleric52_dispelMagic();
+ static SpellResult cleric54_removeCondition();
+ static SpellResult cleric55_restoreEnergy();
+ static SpellResult cleric62_raiseDead();
+ static SpellResult cleric63_rejuvinate();
+ static SpellResult cleric64_stoneToFlesh();
+ static SpellResult cleric65_townPortal();
+ static SpellResult cleric73_protectionFromElements();
+ static SpellResult cleric74_resurrection();
- static SpellResult wizard12_detectMagic(Character *chr);
- static SpellResult wizard15_leatherSkin(Character *chr);
- static SpellResult wizard16_light(Character *chr) {
- return cleric15_light(chr);
+ static SpellResult wizard12_detectMagic();
+ static SpellResult wizard15_leatherSkin();
+ static SpellResult wizard16_light() {
+ return cleric15_light();
}
- static SpellResult wizard17_location(Character *chr);
- static SpellResult wizard24_jump(Character *chr);
- static SpellResult wizard25_levitate(Character *chr);
- static SpellResult wizard32_fly(Character *chr);
- static SpellResult wizard45_guardDog(Character *chr);
- static SpellResult wizard46_psychicProtection(Character *chr);
- static SpellResult wizard52_dispelMagic(Character *chr) {
- return cleric52_dispelMagic(chr);
+ static SpellResult wizard17_location();
+ static SpellResult wizard24_jump();
+ static SpellResult wizard25_levitate();
+ static SpellResult wizard32_fly();
+ static SpellResult wizard45_guardDog();
+ static SpellResult wizard46_psychicProtection();
+ static SpellResult wizard52_dispelMagic() {
+ return cleric52_dispelMagic();
}
- static SpellResult wizard54_shelter(Character *chr);
- static SpellResult wizard55_teleport(Character *chr);
- static SpellResult wizard63_etherialize(Character *chr);
- static SpellResult wizard64_protectionFromMagic(Character *chr);
- static SpellResult wizard65_rechargeItem(Character *chr);
- static SpellResult wizard71_astralSpell(Character *chr);
- static SpellResult wizard72_duplication(Character *chr);
+ static SpellResult wizard54_shelter();
+ static SpellResult wizard55_teleport();
+ static SpellResult wizard63_etherialize();
+ static SpellResult wizard64_protectionFromMagic();
+ static SpellResult wizard65_rechargeItem();
+ static SpellResult wizard71_astralSpell();
+ static SpellResult wizard72_duplication();
static SpellFn SPELLS[SPELLS_COUNT];
public:
/**
* Casts a spell
- * @returns If false, display a 'Done' message.
- * If true, spell has done it's own UI display
*/
- static SpellResult cast(int spell, Character *chr);
+ static SpellResult cast(uint spell, Character *destChar);
+ static SpellResult cast(uint spell, int destMonsterIdx);
};
} // namespace Game
Commit: 5bf2fb81c4a9642b3ecf8fb7eecbfbaafc5fbc64
https://github.com/scummvm/scummvm/commit/5bf2fb81c4a9642b3ecf8fb7eecbfbaafc5fbc64
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: Misc spell fixes
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 92ecd080f94..ff74d75deea 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -800,8 +800,19 @@ spells:
failed: "SPELL FAILED"
enter_to_cast: "'ENTER' TO CAST"
- cast_on: "CAST ON: '1'-'%d'?"
+ cast_on_char: "CAST ON: '1'-'%d'?"
+ cast_on_monster: "CAST ON: 'A'-'%c'?"
which_town: "WHICH TOWN (1-5)?"
+ monster_effects:
+ 0: "IS SCARED"
+ 1: "IS BLINDED"
+ 2: "IS SILENCED"
+ 3: "IS MINDLESS"
+ 4: "IS SLEPT"
+ 5: "IS HELD"
+ 6: "IS WEBBED"
+ 7: "IS PARALYZED"
+ 8: "IS AFFECTED"
monster_spells:
casts: "CASTS "
fails_to_cast: "FAILS TO CAST A SPELL"
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 8b67f519ce0..1240370a97f 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -206,8 +206,8 @@ SpellResult SpellsParty::cleric13_blind() {
s._newCondition = BLINDED;
s._resistanceType = static_cast<Resistance>((int)s._resistanceType + 1);
- iterateMonsters1();
- return SR_SUCCESS_DONE;
+ g_events->send("Combat", GameMessage("ITERATE1"));
+ return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric14_firstAid() {
@@ -641,6 +641,8 @@ SpellResult SpellsParty::wizard72_duplication() {
void SpellsParty::restoreHp(Character *destChar, uint16 hp) {
destChar->_hpBase = MIN((int)(_destChar->_hpBase + hp), (int)_destChar->_hpMax);
+ if (!(destChar->_condition & BAD_CONDITION))
+ destChar->_condition &= ~UNCONSCIOUS;
}
void SpellsParty::addLight(int amount) {
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index 7a577f7742a..df807ac7249 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -110,7 +110,7 @@ void CastSpell::draw() {
case SELECT_CHAR:
writeString(22, 3, Common::String::format(
- STRING["spells.cast_on"].c_str(),
+ STRING["spells.cast_on_char"].c_str(),
(int)g_globals->_party.size()
));
break;
Commit: 8e90a6f75258b9693d643ee2ff84a26e7aa76734
https://github.com/scummvm/scummvm/commit/8e90a6f75258b9693d643ee2ff84a26e7aa76734
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: Implemented turn undead spell
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
engines/mm/mm1/globals.h
engines/mm/mm1/messages.h
engines/mm/mm1/sound.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ff74d75deea..de14e0ce173 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -798,6 +798,8 @@ spells:
magic_doesnt_work: "MAGIC DOESN'T WORK HERE"
outdoors_only: "OUTDOOR ONLY"
failed: "SPELL FAILED"
+ no_effect: "NO EFFECT!"
+ monsters_destroyed: "SOME MONSTERS WERE DESTROYED!"
enter_to_cast: "'ENTER' TO CAST"
cast_on_char: "CAST ON: '1'-'%d'?"
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index b5d02eb6d85..d00c29b34b4 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -44,6 +44,10 @@ enum MonsterStatusFlag {
MONFLAG_PARALYZED = 0x80, MONFLAG_DEAD = 0xff
};
+enum Field19 {
+ FIELD19_UNDEAD = 0x80
+};
+
enum Fiedl1A {
FIELD1A_80 = 0x80
};
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 7e817eda874..cf3b7cd6d04 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -22,15 +22,21 @@
#include "mm/mm1/game/combat.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
namespace Game {
Combat::Combat() : _monsterList(g_globals->_encounters._monsterList) {
+ g_globals->_combat = this;
clear();
}
+Combat::~Combat() {
+ g_globals->_combat = nullptr;
+}
+
void Combat::clear() {
Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
@@ -61,6 +67,10 @@ void Combat::clear() {
_attackAttr2.clear();
_timesHit = 0;
_isShooting = false;
+ _monstersDestroyedCtr = 0;
+
+ _turnUndeadUsed = false;
+ _monstersDestroyedCtr = 0;
// TODO: clear everything
@@ -821,6 +831,43 @@ void Combat::updateMonsterStatus() {
}
}
+void Combat::displaySpellResult(const InfoMessage &msg) {
+ // TODO: displaySpellResult
+ warning("TODO: displaySpellResult");
+}
+
+void Combat::turnUndead() {
+ if (_turnUndeadUsed) {
+ // Already been used in the current combat, can't be used again
+ displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
+
+ } else {
+ _turnUndeadUsed = true;
+
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ monsterSetPtr(i);
+ Monster *monster = _monsterP;
+
+ if ((monster->_field19 & FIELD19_UNDEAD) &&
+ (getRandomNumber(20) + g_globals->_currCharacter->_level) >=
+ (_arr1[i] * 2 + 10)) {
+ destroyUndead();
+ ++_monstersDestroyedCtr;
+ }
+ }
+
+ if (_monstersDestroyedCtr)
+ displaySpellResult(InfoMessage(5, 1, STRING["spells.monsters_destroyed"]));
+ }
+
+ _arr3[_currentChar] = 1;
+}
+
+void Combat::destroyUndead() {
+ _monsterStatus[getMonsterIndex()] = 0xff;
+ Sound::sound2(SOUND_9);
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 190bd5b944c..ad396a66c64 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -79,6 +79,9 @@ protected:
};
Mode _mode = SELECT_OPTION;
+ int _monstersDestroyedCtr = 0;
+ bool _turnUndeadUsed = false;
+
/**
* Constructor
*/
@@ -87,7 +90,7 @@ protected:
/**
* Destructor
*/
- virtual ~Combat() {}
+ virtual ~Combat();
/**
* Sets the combat display mode
@@ -231,6 +234,17 @@ protected:
* Updates a monster's status
*/
void updateMonsterStatus();
+
+private:
+ void destroyUndead();
+
+public:
+ /**
+ * Display a combat spell's result
+ */
+ virtual void displaySpellResult(const InfoMessage &msg);
+
+ void turnUndead();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 1240370a97f..391eb3d8616 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -46,7 +46,7 @@ SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
cleric15_light,
cleric16_powerCure,
cleric17_protectionFromFear,
- placeholder,
+ cleric18_turnUndead,
cleric21_cureWounds,
placeholder,
placeholder,
@@ -231,10 +231,20 @@ SpellResult SpellsParty::cleric16_powerCure() {
SpellResult SpellsParty::cleric17_protectionFromFear() {
g_globals->_activeSpells._s.fear =
- MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
+SpellResult SpellsParty::cleric18_turnUndead() {
+ if (g_globals->_currCharacter->_alignment !=
+ g_globals->_currCharacter->_alignmentInitial)
+ // Cleric's current alignment differs from initial, so spell fails
+ return SR_FAILED;
+
+ g_globals->_combat->turnUndead();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric21_cureWounds() {
restoreHp(_destChar, 16);
return SR_SUCCESS_DONE;
@@ -242,19 +252,19 @@ SpellResult SpellsParty::cleric21_cureWounds() {
SpellResult SpellsParty::cleric24_protectionFromCold() {
g_globals->_activeSpells._s.cold =
- MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric25_protectionFromIce() {
g_globals->_activeSpells._s.fire =
- MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric26_protectionFromPoison() {
g_globals->_activeSpells._s.poison =
- MIN(g_globals->_currCharacter->_level._current + 20, 255);
+ MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
@@ -650,12 +660,8 @@ void SpellsParty::addLight(int amount) {
g_events->send("Game", GameMessage("UPDATE"));
}
-void SpellsParty::iterateMonsters1() {
-
-}
-
-void SpellsParty::iterateMonsters2() {
-
+void SpellsParty::display(const InfoMessage &msg) {
+ g_globals->_combat->displaySpellResult(msg);
}
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index dba94f66dec..85968e36d5b 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -23,6 +23,7 @@
#define MM1_GAME_SPELLS_H
#include "mm/mm1/data/character.h"
+#include "mm/mm1/messages.h"
namespace MM {
namespace MM1 {
@@ -60,8 +61,10 @@ private:
*/
static void addLight(int amount);
- static void iterateMonsters1();
- static void iterateMonsters2();
+ /**
+ * Display a message
+ */
+ static void display(const InfoMessage &msg);
private:
static SpellResult placeholder() {
@@ -74,6 +77,7 @@ private:
static SpellResult cleric15_light();
static SpellResult cleric16_powerCure();
static SpellResult cleric17_protectionFromFear();
+ static SpellResult cleric18_turnUndead();
static SpellResult cleric21_cureWounds();
static SpellResult cleric24_protectionFromCold();
static SpellResult cleric25_protectionFromIce();
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index fa4ee88f00b..5860ad4098b 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -33,6 +33,7 @@
#include "mm/mm1/data/monsters.h"
#include "mm/mm1/data/roster.h"
#include "mm/mm1/data/treasure.h"
+#include "mm/mm1/game/combat.h"
#include "mm/mm1/game/encounter.h"
#include "mm/mm1/maps/maps.h"
@@ -51,6 +52,7 @@ public:
BitmapFont _font;
bool _heardRumor = false;
Game::Encounter _encounters;
+ Game::Combat *_combat = nullptr;
Monsters _monsters;
Treasure _treasure;
byte _delay = 5;
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 8ef0ff64d91..1cfeb8272db 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -73,9 +73,14 @@ struct MouseUpMessage : public MouseMessage {
struct GameMessage : public Message {
Common::String _name;
+ int _value;
+
GameMessage() : Message() {}
GameMessage(const Common::String &name) : Message(),
- _name(name) {}
+ _name(name), _value(-1) {}
+ GameMessage(const Common::String &name, int value) : Message(),
+ _name(name), _value(value) {
+ }
};
struct HeaderMessage : public Message {
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
index 7873f936e7c..1adeeb0ff11 100644
--- a/engines/mm/mm1/sound.h
+++ b/engines/mm/mm1/sound.h
@@ -26,7 +26,8 @@ namespace MM {
namespace MM1 {
enum SoundId {
- SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3, SOUND_4 = 4, SOUND_8 = 8
+ SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3, SOUND_4 = 4, SOUND_8 = 8,
+ SOUND_9 = 9
};
class Sound {
Commit: e1d14b2ed8fff52fe6364c3751dce59f52b974e1
https://github.com/scummvm/scummvm/commit/e1d14b2ed8fff52fe6364c3751dce59f52b974e1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: Adding combat cleric spells
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index cf3b7cd6d04..6d5e6689ebc 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -836,6 +836,14 @@ void Combat::displaySpellResult(const InfoMessage &msg) {
warning("TODO: displaySpellResult");
}
+void Combat::iterateMonsters1() {
+ // TODO: iterateMonsters1
+}
+
+void Combat::iterateMonsters2() {
+ // TODO: iterateMonsters2
+}
+
void Combat::turnUndead() {
if (_turnUndeadUsed) {
// Already been used in the current combat, can't be used again
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index ad396a66c64..daf74f2503b 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -244,6 +244,9 @@ public:
*/
virtual void displaySpellResult(const InfoMessage &msg);
+ void iterateMonsters1();
+ void iterateMonsters2();
+
void turnUndead();
};
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 391eb3d8616..8dda623f6f2 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -206,12 +206,12 @@ SpellResult SpellsParty::cleric13_blind() {
s._newCondition = BLINDED;
s._resistanceType = static_cast<Resistance>((int)s._resistanceType + 1);
- g_events->send("Combat", GameMessage("ITERATE1"));
+ g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric14_firstAid() {
- restoreHp(_destChar, 8);
+ restoreHp(8);
return SR_SUCCESS_DONE;
}
@@ -225,7 +225,7 @@ SpellResult SpellsParty::cleric16_powerCure() {
for (uint i = 0; i < g_globals->_currCharacter->_level._current; ++i)
totalHp += g_engine->getRandomNumber(10);
- restoreHp(_destChar, MIN(totalHp, 250));
+ restoreHp(MIN(totalHp, 250));
return SR_SUCCESS_DONE;
}
@@ -246,10 +246,32 @@ SpellResult SpellsParty::cleric18_turnUndead() {
}
SpellResult SpellsParty::cleric21_cureWounds() {
- restoreHp(_destChar, 16);
+ restoreHp(16);
return SR_SUCCESS_DONE;
}
+SpellResult SpellsParty::cleric22_heroism() {
+ if (g_globals->_currCharacter->_alignment != _destChar->_alignment ||
+ _destChar->_level._current != _destChar->_level._base)
+ return SR_FAILED;
+
+ _destChar->_level._current = MIN(
+ (int)_destChar->_level._current + 2, 255);
+ restoreHp(6);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::cleric23_pain() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._newCondition = getRandomNumber(6) + getRandomNumber(6);
+ ss._mmVal1++;
+ ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+ ss._mmVal2 = 6;
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric24_protectionFromCold() {
g_globals->_activeSpells._s.cold =
MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
@@ -390,7 +412,7 @@ SpellResult SpellsParty::cleric54_removeCondition() {
if (!_destChar->_hpBase)
_destChar->_hpBase = 1;
- restoreHp(_destChar, 1);
+ restoreHp(1);
return SR_SUCCESS_DONE;
}
@@ -517,7 +539,7 @@ SpellResult SpellsParty::cleric74_resurrection() {
_destChar->_endurance._base = MAX((int)_destChar->_endurance._base - 1, 1);
_destChar->_condition = FINE;
- restoreHp(_destChar, 1);
+ restoreHp(1);
return SR_SUCCESS_DONE;
}
@@ -649,10 +671,10 @@ SpellResult SpellsParty::wizard72_duplication() {
return SR_FAILED;
}
-void SpellsParty::restoreHp(Character *destChar, uint16 hp) {
- destChar->_hpBase = MIN((int)(_destChar->_hpBase + hp), (int)_destChar->_hpMax);
- if (!(destChar->_condition & BAD_CONDITION))
- destChar->_condition &= ~UNCONSCIOUS;
+void SpellsParty::restoreHp(uint16 hp) {
+ _destChar->_hpBase = MIN((int)(_destChar->_hpBase + hp), (int)_destChar->_hpMax);
+ if (!(_destChar->_condition & BAD_CONDITION))
+ _destChar->_condition &= ~UNCONSCIOUS;
}
void SpellsParty::addLight(int amount) {
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 85968e36d5b..2ec08cd0113 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -23,6 +23,7 @@
#define MM1_GAME_SPELLS_H
#include "mm/mm1/data/character.h"
+#include "mm/mm1/game/game_logic.h"
#include "mm/mm1/messages.h"
namespace MM {
@@ -40,7 +41,7 @@ extern byte FLY_MAP_ID2[20];
extern byte FLY_MAP_X[20];
extern byte FLY_MAP_Y[20];
-class SpellsParty {
+class SpellsParty : public GameLogic {
typedef SpellResult(*SpellFn)();
private:
static Character *_destChar;
@@ -54,7 +55,7 @@ private:
/**
* Restores an amount of Hp
*/
- static void restoreHp(Character *chr, uint16 hp);
+ static void restoreHp(uint16 hp);
/**
* Increases light duration
@@ -79,6 +80,8 @@ private:
static SpellResult cleric17_protectionFromFear();
static SpellResult cleric18_turnUndead();
static SpellResult cleric21_cureWounds();
+ static SpellResult cleric22_heroism();
+ static SpellResult cleric23_pain();
static SpellResult cleric24_protectionFromCold();
static SpellResult cleric25_protectionFromIce();
static SpellResult cleric26_protectionFromPoison();
Commit: 5883e84eb9f25bf6cc37301d6e3822978a8eba2d
https://github.com/scummvm/scummvm/commit/5883e84eb9f25bf6cc37301d6e3822978a8eba2d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: More cleric combat spells
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 6d5e6689ebc..b2d4fa6874f 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -876,6 +876,15 @@ void Combat::destroyUndead() {
Sound::sound2(SOUND_9);
}
+void Combat::summonLightning(int destMonsterIndex) {
+ // TODO: Summon lightning
+ //SpellsState &ss = g_globals->_spellsState;
+
+ if (destMonsterIndex < _attackerVal) {
+ // TODO
+ }
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index daf74f2503b..3776e26e696 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -248,6 +248,7 @@ public:
void iterateMonsters2();
void turnUndead();
+ void summonLightning(int destMonsterIndex);
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 8dda623f6f2..e42cf9dd53c 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -39,28 +39,28 @@ int SpellsParty::_destMonsterNum;
SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
// Cleric spells
- placeholder,
- placeholder,
- placeholder,
+ cleric11_awaken,
+ cleric12_bless,
+ cleric13_blind,
cleric14_firstAid,
cleric15_light,
cleric16_powerCure,
cleric17_protectionFromFear,
cleric18_turnUndead,
cleric21_cureWounds,
- placeholder,
- placeholder,
+ cleric22_heroism,
+ cleric23_pain,
cleric24_protectionFromCold,
cleric25_protectionFromIce,
cleric26_protectionFromPoison,
- placeholder,
- placeholder,
+ cleric27_silence,
+ cleric28_suggestion,
cleric31_createFood,
cleric32_cureBlindness,
cleric33_cureParalysis,
cleric34_lastingLight,
- placeholder,
- placeholder,
+ cleric35_produceFlame,
+ cleric36_produceFrost,
cleric37_removeQuest,
cleric38_walkOnWater,
cleric41_cureDisease,
@@ -68,8 +68,8 @@ SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
cleric43_protectionFromAcid,
cleric44_protectionFromElectricity,
cleric45_restoreAlignment,
- placeholder,
- placeholder,
+ cleric46_summonLightning,
+ cleric47_superHeroism,
cleric48_surface,
placeholder,
cleric52_dispelMagic,
@@ -290,6 +290,28 @@ SpellResult SpellsParty::cleric26_protectionFromPoison() {
return SR_SUCCESS_DONE;
}
+SpellResult SpellsParty::cleric27_silence() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._mmVal2 = 7;
+ ss._newCondition = SILENCED;
+ ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+
+ g_globals->_combat->iterateMonsters1();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::cleric28_suggestion() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._mmVal2 = 6;
+ ss._newCondition = PARALYZED;
+ ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+
+ g_globals->_combat->iterateMonsters1();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric31_createFood() {
if (_destChar->_food == MAX_FOOD) {
return SR_FAILED;
@@ -322,6 +344,27 @@ SpellResult SpellsParty::cleric34_lastingLight() {
return SR_SUCCESS_SILENT;
}
+SpellResult SpellsParty::cleric35_produceFlame() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+ ss._mmVal2 = 4;
+ ss._newCondition = getRandomNumber(6) +
+ getRandomNumber(6) + getRandomNumber(6);
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::cleric36_produceFrost() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._mmVal2++;
+ ss._newCondition = getRandomNumber(6) +
+ getRandomNumber(6) + getRandomNumber(6);
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric37_removeQuest() {
for (uint i = 0; i < g_globals->_party.size(); ++i)
g_globals->_party[i]._quest = 0;
@@ -369,6 +412,21 @@ SpellResult SpellsParty::cleric45_restoreAlignment() {
return SR_SUCCESS_DONE;
}
+SpellResult SpellsParty::cleric46_summonLightning() {
+ g_globals->_combat->summonLightning(_destMonsterNum);
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::cleric47_superHeroism() {
+ if (_destChar->_level._current != _destChar->_level._base)
+ return SR_FAILED;
+
+ _destChar->_level._current = MIN(
+ (int)_destChar->_level._current + 3, 255);
+ restoreHp(10);
+ return SR_SUCCESS_DONE;
+}
+
SpellResult SpellsParty::cleric48_surface() {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 2ec08cd0113..37306310f42 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -85,10 +85,14 @@ private:
static SpellResult cleric24_protectionFromCold();
static SpellResult cleric25_protectionFromIce();
static SpellResult cleric26_protectionFromPoison();
+ static SpellResult cleric27_silence();
+ static SpellResult cleric28_suggestion();
static SpellResult cleric31_createFood();
static SpellResult cleric32_cureBlindness();
static SpellResult cleric33_cureParalysis();
static SpellResult cleric34_lastingLight();
+ static SpellResult cleric35_produceFlame();
+ static SpellResult cleric36_produceFrost();
static SpellResult cleric37_removeQuest();
static SpellResult cleric38_walkOnWater();
static SpellResult cleric41_cureDisease();
@@ -96,6 +100,8 @@ private:
static SpellResult cleric43_protectionFromAcid();
static SpellResult cleric44_protectionFromElectricity();
static SpellResult cleric45_restoreAlignment();
+ static SpellResult cleric46_summonLightning();
+ static SpellResult cleric47_superHeroism();
static SpellResult cleric48_surface();
static SpellResult cleric52_dispelMagic();
static SpellResult cleric54_removeCondition();
Commit: 9a0bb8f35dbb1f70e8a55e167d57175b64e7cd54
https://github.com/scummvm/scummvm/commit/9a0bb8f35dbb1f70e8a55e167d57175b64e7cd54
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: Starting spells' monster iteration code
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.h
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index de14e0ce173..04361db9634 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -800,6 +800,7 @@ spells:
failed: "SPELL FAILED"
no_effect: "NO EFFECT!"
monsters_destroyed: "SOME MONSTERS WERE DESTROYED!"
+ casts_spell: "CASTS A SPELL:"
enter_to_cast: "'ENTER' TO CAST"
cast_on_char: "CAST ON: '1'-'%d'?"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 3158992c912..6398455a3e5 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -60,7 +60,7 @@ enum Resistance {
RESISTANCE_MAGIC = 0, RESISTANCE_FIRE = 1, RESISTANCE_COLD = 2,
RESISTANCE_ELECTRICITY = 3, RESISTANCE_ACID = 4,
RESISTANCE_FEAR = 5, RESISTANCE_POISON = 6,
- RESISTANCE_PSYCHIC = 7
+ RESISTANCE_PSYCHIC = 7, RESISTANCE_15 = 15
};
enum CharFlags0 {
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index d00c29b34b4..f31e5dadf7c 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -45,6 +45,7 @@ enum MonsterStatusFlag {
};
enum Field19 {
+ FIELD19_LEVEL = 0x7f,
FIELD19_UNDEAD = 0x80
};
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b2d4fa6874f..aa8cc9c72a3 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -837,6 +837,15 @@ void Combat::displaySpellResult(const InfoMessage &msg) {
}
void Combat::iterateMonsters1() {
+ Common::String line1 = Common::String::format("|%s| %s",
+ g_globals->_currCharacter->_name,
+ STRING["spells.casts_spell"].c_str());
+ _spellMonsterCount = _monsterList.size();
+
+ for (;;) {
+ // TODO
+ }
+
// TODO: iterateMonsters1
}
@@ -844,6 +853,19 @@ void Combat::iterateMonsters2() {
// TODO: iterateMonsters2
}
+void Combat::resetDestMonster() {
+ _destMonsterNum = 0;
+ _monsterP = &_monsterList[0];
+ monsterIndexOf();
+ g_globals->_spellsState._resistanceType = RESISTANCE_15;
+}
+
+bool Combat::monsterLevelThreshold() const {
+ int level = _monsterP->_field19 & FIELD19_LEVEL;
+ return (level != 0) &&
+ getRandomNumber(g_globals->_currCharacter->_level + 100) < level;
+}
+
void Combat::turnUndead() {
if (_turnUndeadUsed) {
// Already been used in the current combat, can't be used again
@@ -876,11 +898,11 @@ void Combat::destroyUndead() {
Sound::sound2(SOUND_9);
}
-void Combat::summonLightning(int destMonsterIndex) {
+void Combat::summonLightning() {
// TODO: Summon lightning
//SpellsState &ss = g_globals->_spellsState;
- if (destMonsterIndex < _attackerVal) {
+ if (_destMonsterNum < _attackerVal) {
// TODO
}
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3776e26e696..a3e9efd5d9b 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -79,8 +79,10 @@ protected:
};
Mode _mode = SELECT_OPTION;
+ int _destMonsterNum = 0;
int _monstersDestroyedCtr = 0;
bool _turnUndeadUsed = false;
+ size_t _spellMonsterCount = 0;
/**
* Constructor
@@ -237,6 +239,7 @@ protected:
private:
void destroyUndead();
+ bool monsterLevelThreshold() const;
public:
/**
@@ -246,9 +249,10 @@ public:
void iterateMonsters1();
void iterateMonsters2();
+ void resetDestMonster();
void turnUndead();
- void summonLightning(int destMonsterIndex);
+ void summonLightning();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index e42cf9dd53c..8b1fc05d2b7 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -35,7 +35,6 @@ namespace MM1 {
namespace Game {
Character *SpellsParty::_destChar;
-int SpellsParty::_destMonsterNum;
SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
// Cleric spells
@@ -119,7 +118,7 @@ SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
wizard46_psychicProtection,
placeholder,
placeholder,
- placeholder,
+ cleric51_deadlySwarm,
wizard52_dispelMagic,
placeholder,
wizard54_shelter,
@@ -167,15 +166,6 @@ byte FLY_MAP_Y[20] = {
SpellResult SpellsParty::cast(uint spell, Character *destChar) {
assert(spell < SPELLS_COUNT);
_destChar = destChar;
- _destMonsterNum = -1;
-
- return SPELLS[spell]();
-}
-
-SpellResult SpellsParty::cast(uint spell, int destMonsterIdx) {
- assert(spell < SPELLS_COUNT);
- _destChar = nullptr;
- _destMonsterNum = destMonsterIdx;
return SPELLS[spell]();
}
@@ -413,7 +403,7 @@ SpellResult SpellsParty::cleric45_restoreAlignment() {
}
SpellResult SpellsParty::cleric46_summonLightning() {
- g_globals->_combat->summonLightning(_destMonsterNum);
+ g_globals->_combat->summonLightning();
return SR_SUCCESS_SILENT;
}
@@ -442,6 +432,17 @@ SpellResult SpellsParty::cleric48_surface() {
}
}
+SpellResult SpellsParty::cleric51_deadlySwarm() {
+ SpellsState &ss = g_globals->_spellsState;
+ g_globals->_combat->resetDestMonster();
+ ss._mmVal1++;
+ ss._mmVal2 = 0;
+ ss._newCondition = getRandomNumber(10) + getRandomNumber(10);
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric52_dispelMagic() {
Maps::Map &map = *g_maps->_currentMap;
if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DISPEL_THRESHOLD]) {
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 37306310f42..457dc19128b 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -45,7 +45,6 @@ class SpellsParty : public GameLogic {
typedef SpellResult(*SpellFn)();
private:
static Character *_destChar;
- static int _destMonsterNum;
private:
/**
* Returns true if in combat
@@ -103,6 +102,7 @@ private:
static SpellResult cleric46_summonLightning();
static SpellResult cleric47_superHeroism();
static SpellResult cleric48_surface();
+ static SpellResult cleric51_deadlySwarm();
static SpellResult cleric52_dispelMagic();
static SpellResult cleric54_removeCondition();
static SpellResult cleric55_restoreEnergy();
@@ -141,7 +141,7 @@ public:
* Casts a spell
*/
static SpellResult cast(uint spell, Character *destChar);
- static SpellResult cast(uint spell, int destMonsterIdx);
+ static SpellResult cast(uint spellx);
};
} // namespace Game
Commit: ce459a55963160bfb76cbc60acef2d3dff2d7174
https://github.com/scummvm/scummvm/commit/ce459a55963160bfb76cbc60acef2d3dff2d7174
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: Fleshing out iterateMonsters1
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/spells_state.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 04361db9634..ebb3e59d722 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -806,6 +806,7 @@ spells:
cast_on_char: "CAST ON: '1'-'%d'?"
cast_on_monster: "CAST ON: 'A'-'%c'?"
which_town: "WHICH TOWN (1-5)?"
+ is_not_affected: "IS NOT AFFECTED!"
monster_effects:
0: "IS SCARED"
1: "IS BLINDED"
diff --git a/engines/mm/mm1/data/spells_state.h b/engines/mm/mm1/data/spells_state.h
index 22c3871f80d..6142a14f93a 100644
--- a/engines/mm/mm1/data/spells_state.h
+++ b/engines/mm/mm1/data/spells_state.h
@@ -29,10 +29,10 @@ namespace MM {
namespace MM1 {
struct SpellsState {
- int _mmVal1 = 0, _mmVal2 = 0;
- int _mmVal5 = 0;
- int _mmVal7 = 0;
- Resistance _resistanceType = RESISTANCE_MAGIC;
+ byte _mmVal1 = 0, _mmVal2 = 0;
+ byte _mmVal5 = 0;
+ byte _mmVal7 = 0;
+ byte _resistanceType = RESISTANCE_MAGIC;
byte _newCondition = 0;
/**
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index aa8cc9c72a3..fe35669527b 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -832,7 +832,12 @@ void Combat::updateMonsterStatus() {
}
void Combat::displaySpellResult(const InfoMessage &msg) {
- // TODO: displaySpellResult
+ Common::Array<InfoMessage> msgs;
+ msgs.push_back(msg);
+ displaySpellResult(msgs);
+}
+
+void Combat::displaySpellResult(const Common::Array<InfoMessage> &msgs) {
warning("TODO: displaySpellResult");
}
@@ -840,13 +845,69 @@ void Combat::iterateMonsters1() {
Common::String line1 = Common::String::format("|%s| %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
+ Common::Array<InfoMessage> msgs;
_spellMonsterCount = _monsterList.size();
+ // TODO: Finish loop
for (;;) {
- // TODO
- }
+ const Common::String monsterName = _monsterP->_name;
+ bool affects = !monsterLevelThreshold();
+ if (affects) {
+ if (g_globals->_spellsState._mmVal1) {
+ proc2();
+ affects = !_val9;
+ }
+ }
+
+ byte idx = g_globals->_spellsState._mmVal2;
+ if (affects && idx) {
+ if (--idx >= 8)
+ idx = 0;
+
+ static const byte FLAGS[8] = {
+ 0x40, 0x20, 0x60, 0x10, 8, 4, 2, 1
+ };
+ affects = (_monsterP->_field1a & FLAGS[idx]) != FLAGS[idx];
+ }
+
+ Common::String effect;
+ if (!affects) {
+ effect = STRING["spells.is_not_affected"];
+
+ } else {
+ _monsterStatus[getMonsterIndex()] |=
+ g_globals->_spellsState._newCondition;
+
+ byte bits = g_globals->_spellsState._newCondition;
+ int effectNum;
+ for (effectNum = 0; effectNum < 8; ++effectNum, bits >>= 1) {
+ if (bits & 1)
+ break;
+ }
+
+ effect = STRING[Common::String::format(
+ "spells.monster_effects.%d", effectNum)];
+ }
+
+ msgs.push_back(InfoMessage(
+ 0, 0, line1,
+ 0, 2, Common::String::format("%s %s",
+ monsterName.c_str(),
+ STRING["spells.is_not_affected"].c_str()
+ )
+ ));
+
+ if (!--g_globals->_spellsState._resistanceType)
+ break;
+ ++_destMonsterNum;
+ if ((int)_spellMonsterCount <= _destMonsterNum)
+ break;
+ if (((int)_monsterList.size() + _destMonsterNum - _spellMonsterCount) < 0)
+ break;
- // TODO: iterateMonsters1
+ // TODO: Redraw monster list, display message, and wait
+ // before moving to next monster
+ }
}
void Combat::iterateMonsters2() {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index a3e9efd5d9b..3c3818c99b6 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -245,7 +245,8 @@ public:
/**
* Display a combat spell's result
*/
- virtual void displaySpellResult(const InfoMessage &msg);
+ virtual void displaySpellResult(const Common::Array<InfoMessage> &msgs);
+ void displaySpellResult(const InfoMessage &msg);
void iterateMonsters1();
void iterateMonsters2();
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 8b1fc05d2b7..90dee4214a7 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -255,7 +255,7 @@ SpellResult SpellsParty::cleric23_pain() {
SpellsState &ss = g_globals->_spellsState;
ss._newCondition = getRandomNumber(6) + getRandomNumber(6);
ss._mmVal1++;
- ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+ ss._resistanceType++;
ss._mmVal2 = 6;
g_globals->_combat->iterateMonsters2();
@@ -285,7 +285,7 @@ SpellResult SpellsParty::cleric27_silence() {
ss._mmVal1++;
ss._mmVal2 = 7;
ss._newCondition = SILENCED;
- ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+ ss._resistanceType++;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
@@ -296,7 +296,7 @@ SpellResult SpellsParty::cleric28_suggestion() {
ss._mmVal1++;
ss._mmVal2 = 6;
ss._newCondition = PARALYZED;
- ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+ ss._resistanceType++;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
@@ -337,7 +337,7 @@ SpellResult SpellsParty::cleric34_lastingLight() {
SpellResult SpellsParty::cleric35_produceFlame() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
- ss._resistanceType = (Resistance)((int)ss._resistanceType + 1);
+ ss._resistanceType++;
ss._mmVal2 = 4;
ss._newCondition = getRandomNumber(6) +
getRandomNumber(6) + getRandomNumber(6);
Commit: 14a91ec61e324f6644b391eaf640197b393496bd
https://github.com/scummvm/scummvm/commit/14a91ec61e324f6644b391eaf640197b393496bd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: Finish iterateMonsters1
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index fe35669527b..5573de3e136 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -842,72 +842,77 @@ void Combat::displaySpellResult(const Common::Array<InfoMessage> &msgs) {
}
void Combat::iterateMonsters1() {
+ _spellMonsterCount = _monsterList.size();
+ iterateMonsters1Inner();
+}
+
+void Combat::iterateMonsters1Inner() {
Common::String line1 = Common::String::format("|%s| %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
- Common::Array<InfoMessage> msgs;
- _spellMonsterCount = _monsterList.size();
- // TODO: Finish loop
- for (;;) {
- const Common::String monsterName = _monsterP->_name;
- bool affects = !monsterLevelThreshold();
- if (affects) {
- if (g_globals->_spellsState._mmVal1) {
- proc2();
- affects = !_val9;
- }
+ const Common::String monsterName = _monsterP->_name;
+ bool affects = !monsterLevelThreshold();
+ if (affects) {
+ if (g_globals->_spellsState._mmVal1) {
+ proc2();
+ affects = !_val9;
}
+ }
- byte idx = g_globals->_spellsState._mmVal2;
- if (affects && idx) {
- if (--idx >= 8)
- idx = 0;
+ byte idx = g_globals->_spellsState._mmVal2;
+ if (affects && idx) {
+ if (--idx >= 8)
+ idx = 0;
- static const byte FLAGS[8] = {
- 0x40, 0x20, 0x60, 0x10, 8, 4, 2, 1
- };
- affects = (_monsterP->_field1a & FLAGS[idx]) != FLAGS[idx];
- }
+ static const byte FLAGS[8] = {
+ 0x40, 0x20, 0x60, 0x10, 8, 4, 2, 1
+ };
+ affects = (_monsterP->_field1a & FLAGS[idx]) != FLAGS[idx];
+ }
- Common::String effect;
- if (!affects) {
- effect = STRING["spells.is_not_affected"];
+ Common::String effect;
+ if (!affects) {
+ effect = STRING["spells.is_not_affected"];
- } else {
- _monsterStatus[getMonsterIndex()] |=
- g_globals->_spellsState._newCondition;
-
- byte bits = g_globals->_spellsState._newCondition;
- int effectNum;
- for (effectNum = 0; effectNum < 8; ++effectNum, bits >>= 1) {
- if (bits & 1)
- break;
- }
+ } else {
+ _monsterStatus[getMonsterIndex()] |=
+ g_globals->_spellsState._newCondition;
- effect = STRING[Common::String::format(
- "spells.monster_effects.%d", effectNum)];
+ byte bits = g_globals->_spellsState._newCondition;
+ int effectNum;
+ for (effectNum = 0; effectNum < 8; ++effectNum, bits >>= 1) {
+ if (bits & 1)
+ break;
}
- msgs.push_back(InfoMessage(
- 0, 0, line1,
- 0, 2, Common::String::format("%s %s",
- monsterName.c_str(),
- STRING["spells.is_not_affected"].c_str()
- )
- ));
+ effect = STRING[Common::String::format(
+ "spells.monster_effects.%d", effectNum)];
+ }
- if (!--g_globals->_spellsState._resistanceType)
- break;
+ InfoMessage msg(
+ 0, 0, line1,
+ 0, 2, Common::String::format("%s %s",
+ monsterName.c_str(), effect.c_str()
+ ));
+
+ msg._delaySeconds = 3;
+
+ bool isEnd = !--g_globals->_spellsState._resistanceType;
+ if (!isEnd) {
++_destMonsterNum;
if ((int)_spellMonsterCount <= _destMonsterNum)
- break;
- if (((int)_monsterList.size() + _destMonsterNum - _spellMonsterCount) < 0)
- break;
+ isEnd = true;
+ }
+ if (!isEnd)
+ isEnd = ((int)_monsterList.size() + _destMonsterNum - _spellMonsterCount) < 0;
- // TODO: Redraw monster list, display message, and wait
- // before moving to next monster
- }
+ if (!isEnd) {
+ // Move to next iteration after display timeout
+ msg._ynCallback = []() {
+ g_globals->_combat->iterateMonsters1Inner();
+ };
+ }
}
void Combat::iterateMonsters2() {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3c3818c99b6..afa0b2862d1 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -240,6 +240,7 @@ protected:
private:
void destroyUndead();
bool monsterLevelThreshold() const;
+ void iterateMonsters1Inner();
public:
/**
Commit: 6166a646d31cd719bf332c869730c5a28fea5992
https://github.com/scummvm/scummvm/commit/6166a646d31cd719bf332c869730c5a28fea5992
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:36+01:00
Commit Message:
MM: MM1: Implemented iterateMonsters2
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ebb3e59d722..119a1edce7d 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -806,7 +806,18 @@ spells:
cast_on_char: "CAST ON: '1'-'%d'?"
cast_on_monster: "CAST ON: 'A'-'%c'?"
which_town: "WHICH TOWN (1-5)?"
- is_not_affected: "IS NOT AFFECTED!"
+ char_effects:
+ 0: "IS SLEPT"
+ 1: "IS BLINDED"
+ 2: "IS SILENCED"
+ 3: "IS DISEASED"
+ 4: "IS POISONED"
+ 5: "IS PARALYZED"
+ 6: "IS RENDERED UNCONSCIOUS"
+ 7: "IS KILLED"
+ 8: "IS TURNED TO STONE"
+ 9: "IS ERADICATED"
+ 10: "IS AFFECTED"
monster_effects:
0: "IS SCARED"
1: "IS BLINDED"
@@ -826,6 +837,7 @@ monster_spells:
points: "POINTS"
of_damage: "OF DAMAGE!"
goes_down: "GOES DOWN!!!"
+ and_goes_down: "AND GOES DOWN!!!"
dies: "DIES!"
breathes: "BREATHES"
a_curse: "A CURSE"
@@ -859,19 +871,6 @@ monster_spells:
energy: "ENERGY"
swarm: "SWARM"
breathes: "BREATHES "
- effects:
- 0: "IS SLEPT"
- 1: "IS BLINDED"
- 2: "IS SILENCED"
- 3: "IS DISEASED"
- 4: "IS POISONED"
- 5: "IS PARALYZED"
- 6: "IS RENDERED UNCONSCIOUS"
- 7: "IS KILLED"
- 8: "IS TURNED TO STONE"
- 9: "IS ERADICATED"
- 10: "IS AFFECTED"
-
maps:
poof: "POOF!"
sign: "A SIGN ABOVE THE DOOR READS:\n"
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 5573de3e136..2654cb26eff 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -873,7 +873,7 @@ void Combat::iterateMonsters1Inner() {
Common::String effect;
if (!affects) {
- effect = STRING["spells.is_not_affected"];
+ effect = STRING["monster_spells.not_affected"];
} else {
_monsterStatus[getMonsterIndex()] |=
@@ -913,10 +913,100 @@ void Combat::iterateMonsters1Inner() {
g_globals->_combat->iterateMonsters1Inner();
};
}
+
+ displaySpellResult(msg);
}
void Combat::iterateMonsters2() {
- // TODO: iterateMonsters2
+ _spellMonsterCount = _monsterList.size();
+ iterateMonsters2Inner();
+}
+
+void Combat::iterateMonsters2Inner() {
+ Common::String line1 = Common::String::format("|%s| %s",
+ g_globals->_currCharacter->_name,
+ STRING["spells.casts_spell"].c_str());
+ const Common::String monsterName = _monsterP->_name;
+
+ _damage = g_globals->_spellsState._newCondition;
+
+ bool affects = !monsterLevelThreshold();
+ if (affects) {
+ if (g_globals->_spellsState._mmVal1) {
+ proc2();
+ if (_val9)
+ _damage >>= 1;
+ }
+
+ byte idx = g_globals->_spellsState._mmVal2;
+ if (idx) {
+ if (--idx >= 8)
+ idx = 0;
+
+ static const byte FLAGS[8] = {
+ 0x40, 0x20, 0x60, 0x10, 8, 4, 2, 1
+ };
+ if ((_monsterP->_field1a & FLAGS[idx]) == FLAGS[idx])
+ _damage >>= 2;
+ }
+
+ affects = _damage > 0;
+ }
+
+ InfoMessage msg(0, 0, line1);
+
+ if (!affects) {
+ msg._lines.push_back(Line(
+ 0, 1, Common::String::format("%s %s",
+ monsterName.c_str(),
+ STRING["monster_spells.not_affected"].c_str()
+ )
+ ));
+
+ } else {
+ Common::String line2 = Common::String::format("%s %s %d %s %s",
+ monsterName.c_str(),
+ STRING["monster_spells.takes"].c_str(),
+ _damage,
+ STRING[_damage == 1 ? "monster_spells.point" : "monster_spells.points"].c_str(),
+ STRING["monster_spells.of_damage"].c_str()
+ );
+
+ msg._lines.push_back(Line(0, 1, line2));
+
+ if (_damage >= _arr1[getMonsterIndex()]) {
+ msg._lines.push_back(Line(0, 2, STRING["monster_spells.and_goes_down"]));
+ }
+ }
+
+ msg._delaySeconds = 3;
+
+ bool isEnd = !--g_globals->_spellsState._resistanceType;
+ if (!isEnd) {
+ ++_destMonsterNum;
+ if ((int)_spellMonsterCount <= _destMonsterNum)
+ isEnd = true;
+ }
+ if (!isEnd)
+ isEnd = ((int)_monsterList.size() + _destMonsterNum - _spellMonsterCount) < 0;
+
+ if (!isEnd) {
+ // Move to next iteration after display timeout
+ msg._ynCallback = []() {
+ g_globals->_combat->iterateMonsters2Inner();
+ };
+ } else {
+ msg._ynCallback = []() {
+ g_globals->_combat->updateArr3();
+ };
+ }
+
+ displaySpellResult(msg);
+}
+
+void Combat::updateArr3() {
+ _arr3[_currentChar] = 1;
+ combatLoop();
}
void Combat::resetDestMonster() {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index afa0b2862d1..94620411139 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -241,6 +241,8 @@ private:
void destroyUndead();
bool monsterLevelThreshold() const;
void iterateMonsters1Inner();
+ void iterateMonsters2Inner();
+ void updateArr3();
public:
/**
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index b5edd36541d..261c50fc8fc 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -692,7 +692,7 @@ void SpellsMonsters::writeConditionEffect() {
}
}
- add(STRING[Common::String::format("monster_spellsState.effects.%d",
+ add(STRING[Common::String::format("spells.char_effects.%d",
effectNum)]);
add('!');
}
Commit: 63b879a60701ac2aa698d8c145bf7edff770851b
https://github.com/scummvm/scummvm/commit/63b879a60701ac2aa698d8c145bf7edff770851b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: Add _timeoutCallback as an alias for _ynCallback for clarity
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/maps/map_desert.cpp
engines/mm/mm1/messages.cpp
engines/mm/mm1/messages.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 2654cb26eff..eaf636ce025 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -909,7 +909,7 @@ void Combat::iterateMonsters1Inner() {
if (!isEnd) {
// Move to next iteration after display timeout
- msg._ynCallback = []() {
+ msg._timeoutCallback = []() {
g_globals->_combat->iterateMonsters1Inner();
};
}
@@ -992,7 +992,7 @@ void Combat::iterateMonsters2Inner() {
if (!isEnd) {
// Move to next iteration after display timeout
- msg._ynCallback = []() {
+ msg._timeoutCallback = []() {
g_globals->_combat->iterateMonsters2Inner();
};
} else {
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index d8c67e94f39..3c0693b8b88 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -143,7 +143,7 @@ void Map17::askQuestion(uint partyIndex) {
msg2._lines.push_back(Line(0, 0, STRING["maps.map17.color"]));
msg2._lines.push_back(Line(0, 2, STRING["maps.map17.options"]));
msg2._lines.push_back(Line(16, 5, line));
- msg2._ynCallback = []() {
+ msg2._timeoutCallback = []() {
Map17 &map17 = *static_cast<Map17 *>(g_maps->_currentMap);
map17.askQuestion(map17[VAL1] + 1);
};
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index 41d14dbf6b6..fc84d228f85 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -104,7 +104,7 @@ void Map25::special() {
SoundMessage msg(STRING["maps.map25.weeping"]);
if (getRandomNumber(100) >= 99) {
msg._delaySeconds = 3;
- msg._ynCallback = []() {
+ msg._timeoutCallback = []() {
g_globals->_encounters.execute();
};
}
diff --git a/engines/mm/mm1/maps/map_desert.cpp b/engines/mm/mm1/maps/map_desert.cpp
index 91e4c83d7d8..a67c393de69 100644
--- a/engines/mm/mm1/maps/map_desert.cpp
+++ b/engines/mm/mm1/maps/map_desert.cpp
@@ -66,7 +66,7 @@ void MapDesert::desert() {
switch (_randomMode) {
case RND_BASIC:
if (getRandomNumber(100) == 100) {
- msg._ynCallback = []() {
+ msg._timeoutCallback = []() {
g_globals->_encounters.execute();
};
msg._delaySeconds = 3;
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
index 04665b6d83d..9a16e584d5e 100644
--- a/engines/mm/mm1/messages.cpp
+++ b/engines/mm/mm1/messages.cpp
@@ -89,5 +89,16 @@ InfoMessage::InfoMessage(int x1, int y1, const Common::String &str1,
_lines.push_back(Line(x2, y2, str2));
}
+InfoMessage &InfoMessage::operator=(const InfoMessage &src) {
+ _lines = src._lines;
+ _ynCallback = src._ynCallback;
+ _keyCallback = src._keyCallback;
+ _largeMessage = src._largeMessage;
+ _sound = src._sound;
+ _delaySeconds = src._delaySeconds;
+ return *this;
+}
+
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 1cfeb8272db..ef2510a39ad 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -110,6 +110,7 @@ struct InfoMessage : public Message {
LineArray _lines;
YNCallback _ynCallback = nullptr;
KeyCallback _keyCallback = nullptr;
+ YNCallback &_timeoutCallback = _ynCallback;
bool _largeMessage = false;
bool _sound = false;
int _delaySeconds = 0;
@@ -135,6 +136,8 @@ struct InfoMessage : public Message {
InfoMessage(int x1, int y1, const Common::String &str1,
int x2, int y2, const Common::String &str2,
KeyCallback keyCallback);
+
+ InfoMessage &operator=(const InfoMessage &src);
};
struct SoundMessage : public InfoMessage {
Commit: 88449f23e17c227cad63baab6de596b898a39a88
https://github.com/scummvm/scummvm/commit/88449f23e17c227cad63baab6de596b898a39a88
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: Added remaining cleric combat spells
Changed paths:
engines/mm/mm1/data/spells_state.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
diff --git a/engines/mm/mm1/data/spells_state.h b/engines/mm/mm1/data/spells_state.h
index 6142a14f93a..f1d5987fbf4 100644
--- a/engines/mm/mm1/data/spells_state.h
+++ b/engines/mm/mm1/data/spells_state.h
@@ -33,6 +33,10 @@ struct SpellsState {
byte _mmVal5 = 0;
byte _mmVal7 = 0;
byte _resistanceType = RESISTANCE_MAGIC;
+
+ // TODO: Is this variable different in different contexts?
+ // In some places it's used to hold a new condition,
+ // but others, like moonRay, uses it to hold Hp
byte _newCondition = 0;
/**
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index eaf636ce025..9bf24891c71 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -67,9 +67,9 @@ void Combat::clear() {
_attackAttr2.clear();
_timesHit = 0;
_isShooting = false;
- _monstersDestroyedCtr = 0;
_turnUndeadUsed = false;
+ _divineInterventionUsed = false;
_monstersDestroyedCtr = 0;
// TODO: clear everything
@@ -1016,6 +1016,15 @@ void Combat::resetDestMonster() {
g_globals->_spellsState._resistanceType = RESISTANCE_15;
}
+void Combat::spellFailed() {
+ _arr3[_currentChar] = 1;
+
+ SoundMessage msg(10, 2, Common::String::format("*** %s ***",
+ STRING["spells.failed"].c_str()));
+ msg._delaySeconds = 3;
+ displaySpellResult(msg);
+}
+
bool Combat::monsterLevelThreshold() const {
int level = _monsterP->_field19 & FIELD19_LEVEL;
return (level != 0) &&
@@ -1044,6 +1053,8 @@ void Combat::turnUndead() {
if (_monstersDestroyedCtr)
displaySpellResult(InfoMessage(5, 1, STRING["spells.monsters_destroyed"]));
+ else
+ displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
}
_arr3[_currentChar] = 1;
@@ -1055,12 +1066,92 @@ void Combat::destroyUndead() {
}
void Combat::summonLightning() {
- // TODO: Summon lightning
- //SpellsState &ss = g_globals->_spellsState;
+ SpellsState &ss = g_globals->_spellsState;
if (_destMonsterNum < _attackerVal) {
- // TODO
+ Common::String line1 = Common::String::format("|%s| %s",
+ g_globals->_currCharacter->_name,
+ STRING["spells.casts_spell"].c_str());
+
+ ss._newCondition = g_globals->_currCharacter->_level * 2 + 4;
+ ss._mmVal1++;
+ ss._mmVal2++;
+ ss._resistanceType = RESISTANCE_ELECTRICITY;
+ handlePartyDamage();
+
+ InfoMessage msg(0, 0, line1);
+ msg._delaySeconds = 3;
+ msg._timeoutCallback = []() {
+ g_globals->_combat->summonLightning2();
+ };
+ displaySpellResult(msg);
+ } else {
+ summonLightning2();
+ }
+}
+
+void Combat::summonLightning2() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1 = 1;
+ ss._mmVal2 = 2;
+ ss._resistanceType = RESISTANCE_ELECTRICITY;
+ ss._newCondition = getRandomNumber(29) + 3;
+
+ iterateMonsters2();
+}
+
+void Combat::paralyze() {
+ SpellsState &ss = g_globals->_spellsState;
+ g_globals->_combat->resetDestMonster();
+
+ ss._mmVal1++;
+ ss._mmVal2 = 6;
+ ss._resistanceType = _attackerVal;
+ ss._newCondition = BAD_CONDITION;
+
+ iterateMonsters1();
+}
+
+bool Combat::divineIntervention() {
+ Character &c = *g_globals->_currCharacter;
+ if (c._alignment != c._alignmentInitial || _divineInterventionUsed)
+ return false;
+
+ _divineInterventionUsed = true;
+ int age = (int)c._level + 5;
+ if (c._level > 255)
+ return false;
+
+ c._age = age;
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ c = g_globals->_party[i];
+
+ if (c._condition != ERADICATED) {
+ c._condition = 0;
+ c._hpBase = c._hp;
+ c._hpMax = c._hpBase;
+ }
+ }
+
+ return true;
+}
+
+void Combat::holyWord() {
+ _monstersDestroyedCtr = 0;
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ monsterSetPtr(i);
+ if (_monsterP->_field19 & FIELD19_UNDEAD) {
+ destroyUndead();
+ ++_monstersDestroyedCtr;
+ }
}
+
+ if (_monstersDestroyedCtr)
+ displaySpellResult(InfoMessage(5, 1, STRING["spells.monsters_destroyed"]));
+ else
+ displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
+ _arr3[_currentChar] = 1;
}
} // namespace Game
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 94620411139..46ff1eaad8d 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -82,6 +82,7 @@ protected:
int _destMonsterNum = 0;
int _monstersDestroyedCtr = 0;
bool _turnUndeadUsed = false;
+ bool _divineInterventionUsed = false;
size_t _spellMonsterCount = 0;
/**
@@ -238,11 +239,13 @@ protected:
void updateMonsterStatus();
private:
+ void spellFailed();
void destroyUndead();
bool monsterLevelThreshold() const;
void iterateMonsters1Inner();
void iterateMonsters2Inner();
void updateArr3();
+ void summonLightning2();
public:
/**
@@ -257,6 +260,9 @@ public:
void turnUndead();
void summonLightning();
+ void paralyze();
+ bool divineIntervention();
+ void holyWord();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 339af7cd87e..d5cb1061f8c 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -167,11 +167,6 @@ private:
*/
void handlePartyEffects();
- /**
- * Adds text for damage effects on the party
- */
- void handlePartyDamage();
-
void setCondition(byte newCondition);
void proc9();
@@ -185,6 +180,11 @@ protected:
virtual void dispelParty() = 0;
virtual void removeMonster() = 0;
+ /**
+ * Adds text for damage effects on the party
+ */
+ void handlePartyDamage();
+
public:
SpellsMonsters();
virtual ~SpellsMonsters() {}
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 90dee4214a7..7f5196bf449 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -70,21 +70,21 @@ SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
cleric46_summonLightning,
cleric47_superHeroism,
cleric48_surface,
- placeholder,
+ cleric51_deadlySwarm,
cleric52_dispelMagic,
- placeholder,
+ cleric53_paralyze,
cleric54_removeCondition,
cleric55_restoreEnergy,
- placeholder,
+ cleric61_moonRay,
cleric62_raiseDead,
cleric63_rejuvinate,
cleric64_stoneToFlesh,
cleric65_townPortal,
- placeholder,
- placeholder,
+ cleric71_divineIntervention,
+ cleric72_holyWord,
cleric73_protectionFromElements,
cleric74_resurrection,
- placeholder,
+ cleric75_sunRay,
placeholder,
wizard12_detectMagic,
@@ -463,6 +463,11 @@ SpellResult SpellsParty::cleric52_dispelMagic() {
}
}
+SpellResult SpellsParty::cleric53_paralyze() {
+ g_globals->_combat->paralyze();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric54_removeCondition() {
if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
@@ -489,6 +494,28 @@ SpellResult SpellsParty::cleric55_restoreEnergy() {
}
}
+SpellResult SpellsParty::cleric61_moonRay() {
+ SpellsState &ss = g_globals->_spellsState;
+
+ // Heal the party
+ int hp = getRandomNumber(10) + getRandomNumber(10) +
+ getRandomNumber(10);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ restoreHp(c, hp);
+ }
+
+ // Damage the monsters
+ g_globals->_combat->resetDestMonster();
+ ss._newCondition = hp;
+ ss._mmVal1++;
+ ss._mmVal2 = 5;
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric62_raiseDead() {
if ((_destChar->_condition == ERADICATED) ||
(_destChar->_condition & (BAD_CONDITION | DEAD)) ==
@@ -577,6 +604,20 @@ SpellResult SpellsParty::cleric65_townPortal() {
return SR_SUCCESS_SILENT;
}
+SpellResult SpellsParty::cleric71_divineIntervention() {
+ return g_globals->_combat->divineIntervention() ?
+ SR_SUCCESS_DONE : SR_FAILED;
+}
+
+SpellResult SpellsParty::cleric72_holyWord() {
+ Character &c = *g_globals->_currCharacter;
+ if (c._alignment != c._alignmentInitial)
+ return SR_FAILED;
+
+ g_globals->_combat->holyWord();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::cleric73_protectionFromElements() {
int amount = g_globals->_currCharacter->_level._current + 25;
@@ -603,6 +644,17 @@ SpellResult SpellsParty::cleric74_resurrection() {
return SR_SUCCESS_DONE;
}
+SpellResult SpellsParty::cleric75_sunRay() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._newCondition = getRandomNumber(51) + 49;
+ ss._mmVal1++;
+ ss._mmVal2++;
+ ss._resistanceType = RESISTANCE_FIRE;
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::wizard12_detectMagic() {
Views::Spells::DetectMagic::show();
return SR_SUCCESS_SILENT;
@@ -731,9 +783,13 @@ SpellResult SpellsParty::wizard72_duplication() {
}
void SpellsParty::restoreHp(uint16 hp) {
- _destChar->_hpBase = MIN((int)(_destChar->_hpBase + hp), (int)_destChar->_hpMax);
- if (!(_destChar->_condition & BAD_CONDITION))
- _destChar->_condition &= ~UNCONSCIOUS;
+ restoreHp(*_destChar, hp);
+}
+
+void SpellsParty::restoreHp(Character &c, uint16 hp) {
+ c._hpBase = MIN((int)(c._hpBase + hp), (int)c._hpMax);
+ if (!(c._condition & BAD_CONDITION))
+ c._condition &= ~UNCONSCIOUS;
}
void SpellsParty::addLight(int amount) {
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 457dc19128b..70df77af643 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -54,6 +54,7 @@ private:
/**
* Restores an amount of Hp
*/
+ static void restoreHp(Character &c, uint16 hp);
static void restoreHp(uint16 hp);
/**
@@ -104,14 +105,19 @@ private:
static SpellResult cleric48_surface();
static SpellResult cleric51_deadlySwarm();
static SpellResult cleric52_dispelMagic();
+ static SpellResult cleric53_paralyze();
static SpellResult cleric54_removeCondition();
static SpellResult cleric55_restoreEnergy();
+ static SpellResult cleric61_moonRay();
static SpellResult cleric62_raiseDead();
static SpellResult cleric63_rejuvinate();
static SpellResult cleric64_stoneToFlesh();
static SpellResult cleric65_townPortal();
+ static SpellResult cleric71_divineIntervention();
+ static SpellResult cleric72_holyWord();
static SpellResult cleric73_protectionFromElements();
static SpellResult cleric74_resurrection();
+ static SpellResult cleric75_sunRay();
static SpellResult wizard12_detectMagic();
static SpellResult wizard15_leatherSkin();
Commit: 7f7980e71f0441c875006a4e225ec21d562a345b
https://github.com/scummvm/scummvm/commit/7f7980e71f0441c875006a4e225ec21d562a345b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: Default delay and callback handler for combat spell result messages
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 9bf24891c71..4a17ca3c6a6 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -832,12 +832,19 @@ void Combat::updateMonsterStatus() {
}
void Combat::displaySpellResult(const InfoMessage &msg) {
- Common::Array<InfoMessage> msgs;
- msgs.push_back(msg);
- displaySpellResult(msgs);
+ InfoMessage iMsg = msg;
+ if (iMsg._delaySeconds == 0)
+ iMsg._delaySeconds = 3;
+ if (!iMsg._timeoutCallback) {
+ iMsg._timeoutCallback = []() {
+ g_globals->_combat->combatLoop();
+ };
+ }
+
+ // Descendant view classes will handle message display
}
-void Combat::displaySpellResult(const Common::Array<InfoMessage> &msgs) {
+void displaySpellResult(const Common::Array<InfoMessage> &msgs) {
warning("TODO: displaySpellResult");
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 46ff1eaad8d..2e11a6298b3 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -251,8 +251,7 @@ public:
/**
* Display a combat spell's result
*/
- virtual void displaySpellResult(const Common::Array<InfoMessage> &msgs);
- void displaySpellResult(const InfoMessage &msg);
+ virtual void displaySpellResult(const InfoMessage &msg);
void iterateMonsters1();
void iterateMonsters2();
Commit: 11fa375fc23ebaf2a51f145621289d00ff0f4e0e
https://github.com/scummvm/scummvm/commit/11fa375fc23ebaf2a51f145621289d00ff0f4e0e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: Starting wizard combat spells, identified multiple monster fields
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
engines/mm/mm1/views/combat.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 119a1edce7d..2e0c837cd16 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -806,6 +806,16 @@ spells:
cast_on_char: "CAST ON: '1'-'%d'?"
cast_on_monster: "CAST ON: 'A'-'%c'?"
which_town: "WHICH TOWN (1-5)?"
+
+ info:
+ hp: "HP = "
+ ac: "AC = "
+ speed: "SPEED = "
+ bonus_on_touch: "BONUS ON TOUCH "
+ num_attacks: "# OF ATTACKS = "
+ special_ability: "SPECIAL ABILITY "
+ max_damage: "MAXIMUM DAMAGE = "
+ magic_resistance: "MAGIC RESISTANCE "
char_effects:
0: "IS SLEPT"
1: "IS BLINDED"
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index c75e1cf8aee..cdd670e971b 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -44,15 +44,15 @@ bool Monsters::load() {
mon._field10 = getNextValue(line);
mon._field11 = getNextValue(line);
mon._field12 = getNextValue(line);
- mon._field13 = getNextValue(line);
- mon._field14 = getNextValue(line);
- mon._field15 = getNextValue(line);
+ mon._maxDamage = getNextValue(line);
+ mon._numberOfAttacks = getNextValue(line);
+ mon._speed = getNextValue(line);
mon._experience = getNextValue(line);
mon._field18 = getNextValue(line);
- mon._field19 = getNextValue(line);
+ mon._resistUndead = getNextValue(line);
mon._field1a = getNextValue(line);
- mon._field1b = getNextValue(line);
- mon._field1c = getNextValue(line);
+ mon._bonusOnTouch = getNextValue(line);
+ mon._specialAbility = getNextValue(line);
mon._field1d = getNextValue(line);
mon._field1e = getNextValue(line);
mon._field1f = getNextValue(line);
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index f31e5dadf7c..0d7bf694462 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -44,9 +44,9 @@ enum MonsterStatusFlag {
MONFLAG_PARALYZED = 0x80, MONFLAG_DEAD = 0xff
};
-enum Field19 {
- FIELD19_LEVEL = 0x7f,
- FIELD19_UNDEAD = 0x80
+enum MonsterResistUndead {
+ MAGIC_RESISTANCE = 0x7f,
+ IS_UNDEAD = 0x80
};
enum Fiedl1A {
@@ -64,15 +64,15 @@ struct Monster {
byte _field10;
byte _field11;
byte _field12;
- byte _field13;
- byte _field14;
- byte _field15;
+ byte _maxDamage;
+ byte _numberOfAttacks;
+ byte _speed;
uint16 _experience;
byte _field18;
- byte _field19;
+ byte _resistUndead;
byte _field1a;
- byte _field1b;
- byte _field1c;
+ byte _bonusOnTouch;
+ byte _specialAbility;
byte _field1d;
byte _field1e;
byte _field1f;
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 4a17ca3c6a6..da61346be0d 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -38,8 +38,8 @@ Combat::~Combat() {
}
void Combat::clear() {
- Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_arr2[0], &_arr2[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_monsterHP[0], &_monsterHP[MAX_COMBAT_MONSTERS], 0);
+ Common::fill(&_monsterAC[0], &_monsterAC[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
Common::fill(&_arr4[0], &_arr4[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
@@ -89,8 +89,8 @@ void Combat::loadArrays() {
int val = getRandomNumber(8);
mon._field11 += val;
- _arr1[i] = mon._field11;
- _arr2[i] = mon._field12;
+ _monsterHP[i] = mon._field11;
+ _monsterAC[i] = mon._field12;
monsterIndexOf();
}
@@ -307,7 +307,7 @@ void Combat::loop1() {
_monsterP = &_monsterList[i];
monsterIndexOf();
- if (_monsterP->_field15 && _monsterP->_field15 >= _handicap3
+ if (_monsterP->_speed && _monsterP->_speed >= _handicap3
&& !_arr4[i]) {
_arr4[i] = true;
@@ -487,13 +487,13 @@ bool Combat::monsterChanges() {
monsterSetPtr(i);
if ((_monsterP->_field1e & FIELD1E_40) &&
- (_monsterP->_field11 != _arr1[i])) {
+ (_monsterP->_field11 != _monsterHP[i])) {
_monstersRegenerate = true;
- int newVal = _arr1[i] + 5;
- _arr1[i] = (byte)newVal;
+ int newVal = _monsterHP[i] + 5;
+ _monsterHP[i] = (byte)newVal;
if (newVal >= 256 || newVal >= _monsterP->_field11) {
- _arr1[i] = _monsterP->_field11;
+ _monsterHP[i] = _monsterP->_field11;
}
}
@@ -587,7 +587,7 @@ void Combat::checkMonsterFlees() {
if (getRandomNumber(100) >= threshold) {
_monsterP->_experience = 0;
_monsterP->_field18 = 0;
- _arr1[_monsterIndex] = 0;
+ _monsterHP[_monsterIndex] = 0;
_monsterStatus[_monsterIndex] = MONFLAG_DEAD;
removeMonster();
setMode(MONSTER_FLEES);
@@ -605,17 +605,17 @@ void Combat::checkMonsterSpells() {
if (_monsterStatus[_monsterIndex] & MONFLAG_MINDLESS) {
setMode(MONSTER_WANDERS);
} else {
- if (!_monsterP->_field1c || (_monsterP->_field1c & 0x80) ||
+ if (!_monsterP->_specialAbility || (_monsterP->_specialAbility & 0x80) ||
(getRandomNumber(100) >= _monsterP->_field1d) ||
!(_monsterP->_field1e & 0xf))
checkMonsterActions();
else {
_monsterP->_field1e--;
- if (!_monsterP->_field1c || _monsterP->_field1c >= 33) {
+ if (!_monsterP->_specialAbility || _monsterP->_specialAbility >= 33) {
checkMonsterActions();
} else {
castMonsterSpell(_monsterList[_monsterIndex]._name,
- _monsterP->_field1c);
+ _monsterP->_specialAbility);
setMode(MONSTER_SPELL);
}
return;
@@ -821,12 +821,12 @@ void Combat::addAttackDamage() {
}
void Combat::updateMonsterStatus() {
- int val = _arr1[_monsterIndex] - _damage;
+ int val = _monsterHP[_monsterIndex] - _damage;
if (val <= 0) {
- _arr1[_monsterIndex] = 0;
+ _monsterHP[_monsterIndex] = 0;
_monsterStatus[_monsterIndex] = MONFLAG_DEAD;
} else {
- _arr1[_monsterIndex] = val;
+ _monsterHP[_monsterIndex] = val;
_monsterStatus[_monsterIndex] &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
}
}
@@ -981,7 +981,7 @@ void Combat::iterateMonsters2Inner() {
msg._lines.push_back(Line(0, 1, line2));
- if (_damage >= _arr1[getMonsterIndex()]) {
+ if (_damage >= _monsterHP[getMonsterIndex()]) {
msg._lines.push_back(Line(0, 2, STRING["monster_spells.and_goes_down"]));
}
}
@@ -1033,7 +1033,7 @@ void Combat::spellFailed() {
}
bool Combat::monsterLevelThreshold() const {
- int level = _monsterP->_field19 & FIELD19_LEVEL;
+ int level = _monsterP->_resistUndead & MAGIC_RESISTANCE;
return (level != 0) &&
getRandomNumber(g_globals->_currCharacter->_level + 100) < level;
}
@@ -1050,9 +1050,9 @@ void Combat::turnUndead() {
monsterSetPtr(i);
Monster *monster = _monsterP;
- if ((monster->_field19 & FIELD19_UNDEAD) &&
+ if ((monster->_resistUndead & IS_UNDEAD) &&
(getRandomNumber(20) + g_globals->_currCharacter->_level) >=
- (_arr1[i] * 2 + 10)) {
+ (_monsterHP[i] * 2 + 10)) {
destroyUndead();
++_monstersDestroyedCtr;
}
@@ -1148,7 +1148,7 @@ void Combat::holyWord() {
_monstersDestroyedCtr = 0;
for (uint i = 0; i < _monsterList.size(); ++i) {
monsterSetPtr(i);
- if (_monsterP->_field19 & FIELD19_UNDEAD) {
+ if (_monsterP->_resistUndead & IS_UNDEAD) {
destroyUndead();
++_monstersDestroyedCtr;
}
@@ -1161,6 +1161,56 @@ void Combat::holyWord() {
_arr3[_currentChar] = 1;
}
+#define COL2 21
+void Combat::identifyMonster() {
+ InfoMessage msg;
+ Common::String line;
+
+ line = _monsterList[_destMonsterNum]._name;
+ line += ':';
+ while (line.size() < COL2)
+ line += ' ';
+ line += STRING["spells.info.hp"];
+ line += Common::String::format("%d", _monsterHP[_destMonsterNum]);
+ line += " ";
+ line += STRING["spells.info.ac"];
+ line += Common::String::format("%d", _monsterAC[_destMonsterNum]);
+ msg._lines.push_back(Line(0, 0, line));
+
+ line = STRING["spells.info.speed"];
+ line += Common::String::format("%d", _monsterP->_speed);
+ while (line.size() < COL2)
+ line += ' ';
+ line += STRING["spells.info.bonus_on_touch"];
+ line += _monsterP->_bonusOnTouch ? 'Y' : 'N';
+ msg._lines.push_back(Line(0, 1, line));
+
+ line = STRING["spells.info.num_attacks"];
+ line += Common::String::format("%d", _monsterP->_numberOfAttacks);
+ while (line.size() < COL2)
+ line += ' ';
+ line += STRING["spells.info.special_ability"];
+ line += (_monsterP->_specialAbility & 0x80) ||
+ !_monsterP->_specialAbility ? 'N' : 'Y';
+ msg._lines.push_back(Line(0, 2, line));
+
+ line = STRING["spells.info.max_damage"];
+ line += Common::String::format("%d", _monsterP->_maxDamage);
+ while (line.size() < COL2)
+ line += ' ';
+ line += STRING["spells.info.magic_resistance"];
+ line += Common::String::format("%d",
+ _monsterP->_resistUndead & MAGIC_RESISTANCE);
+ msg._lines.push_back(Line(0, 3, line));
+
+ msg._timeoutCallback = []() {
+ g_globals->_combat->_arr3[g_globals->_combat->_currentChar] = 1;
+ g_globals->_combat->combatLoop();
+ };
+
+ displaySpellResult(msg);
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 2e11a6298b3..dc8633c67f9 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -40,8 +40,8 @@ protected:
int _monstersCount = 0;
Common::Array<Character *> _party;
Monster *_monsterP;
- byte _arr1[MAX_COMBAT_MONSTERS];
- byte _arr2[MAX_COMBAT_MONSTERS];
+ byte _monsterHP[MAX_COMBAT_MONSTERS];
+ byte _monsterAC[MAX_COMBAT_MONSTERS];
int _arr3[MAX_PARTY_SIZE / 2];
byte _arr4[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
@@ -257,11 +257,15 @@ public:
void iterateMonsters2();
void resetDestMonster();
+ // Cleric spells that need access to internal fields
void turnUndead();
void summonLightning();
void paralyze();
bool divineIntervention();
void holyWord();
+
+ // Wizard spells that need access to internal fields
+ void identifyMonster();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 7f5196bf449..a2436648c31 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -86,17 +86,17 @@ SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
cleric74_resurrection,
cleric75_sunRay,
- placeholder,
+ wizard11_awaken,
wizard12_detectMagic,
- placeholder,
- placeholder,
+ wizard13_energyBlast,
+ wizard14_flameArrow,
wizard15_leatherSkin,
wizard16_light,
wizard17_location,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
+ wizard18_sleep,
+ wizard21_electricArrow,
+ wizard22_hypnotize,
+ wizard23_identifyMonster,
wizard24_jump,
wizard25_levitate,
placeholder,
@@ -660,6 +660,31 @@ SpellResult SpellsParty::wizard12_detectMagic() {
return SR_SUCCESS_SILENT;
}
+SpellResult SpellsParty::wizard13_energyBlast() {
+ SpellsState &ss = g_globals->_spellsState;
+ int damage = 0;
+ for (int i = 0; i < g_globals->_currCharacter->_level._current; ++i)
+ damage += getRandomNumber(4);
+
+ ss._newCondition = MIN(damage, 255);
+ ss._mmVal2 = 5;
+ ss._resistanceType++;
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard14_flameArrow() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._newCondition = getRandomNumber(6);
+ ss._mmVal1++;
+ ss._mmVal2 = 1;
+ ss._resistanceType++;
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::wizard15_leatherSkin() {
g_globals->_activeSpells._s.leather_skin = g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
@@ -670,6 +695,33 @@ SpellResult SpellsParty::wizard17_location() {
return SR_SUCCESS_SILENT;
}
+SpellResult SpellsParty::wizard18_sleep() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._mmVal2 = 8;
+ ss._resistanceType = RESISTANCE_FEAR;
+ ss._newCondition = 16;
+
+ g_globals->_combat->iterateMonsters1();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard21_electricArrow() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._newCondition = getRandomNumber(6) + getRandomNumber(6);
+ ss._mmVal1++;
+ ss._resistanceType++;
+ ss._mmVal2 = 2;
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard23_identifyMonster() {
+ g_globals->_combat->identifyMonster();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::wizard24_jump() {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 70df77af643..f0697b184a2 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -119,12 +119,23 @@ private:
static SpellResult cleric74_resurrection();
static SpellResult cleric75_sunRay();
+ static SpellResult wizard11_awaken() {
+ return cleric11_awaken();
+ }
static SpellResult wizard12_detectMagic();
+ static SpellResult wizard13_energyBlast();
+ static SpellResult wizard14_flameArrow();
static SpellResult wizard15_leatherSkin();
static SpellResult wizard16_light() {
return cleric15_light();
}
static SpellResult wizard17_location();
+ static SpellResult wizard18_sleep();
+ static SpellResult wizard21_electricArrow();
+ static SpellResult wizard22_hypnotize() {
+ return cleric28_suggestion();
+ }
+ static SpellResult wizard23_identifyMonster();
static SpellResult wizard24_jump();
static SpellResult wizard25_levitate();
static SpellResult wizard32_fly();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 88f47994a62..9ff4f50c797 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -473,7 +473,7 @@ void Combat::writeMonsterStatus(int monsterNum) {
writeString(STRING[Common::String::format("dialogs.combat.status.%d",
status)]);
- } else if (_arr1[monsterNum] != _monsterP->_field11) {
+ } else if (_monsterHP[monsterNum] != _monsterP->_field11) {
writeDots();
writeString(STRING["dialogs.combat.status.wounded"]);
} else {
Commit: 22995c2987ccfc67011ddcce767972c59c0e9a39
https://github.com/scummvm/scummvm/commit/22995c2987ccfc67011ddcce767972c59c0e9a39
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: Shift displaySpellResult stub code to descendant view
Changed paths:
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 0d7bf694462..84a63c7f719 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -69,7 +69,7 @@ struct Monster {
byte _speed;
uint16 _experience;
byte _field18;
- byte _resistUndead;
+ byte _resistUndead; // MonsterResistUndead
byte _field1a;
byte _bonusOnTouch;
byte _specialAbility;
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index da61346be0d..b37b57a3bc4 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -831,23 +831,6 @@ void Combat::updateMonsterStatus() {
}
}
-void Combat::displaySpellResult(const InfoMessage &msg) {
- InfoMessage iMsg = msg;
- if (iMsg._delaySeconds == 0)
- iMsg._delaySeconds = 3;
- if (!iMsg._timeoutCallback) {
- iMsg._timeoutCallback = []() {
- g_globals->_combat->combatLoop();
- };
- }
-
- // Descendant view classes will handle message display
-}
-
-void displaySpellResult(const Common::Array<InfoMessage> &msgs) {
- warning("TODO: displaySpellResult");
-}
-
void Combat::iterateMonsters1() {
_spellMonsterCount = _monsterList.size();
iterateMonsters1Inner();
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index dc8633c67f9..dae234cbcdb 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -251,7 +251,7 @@ public:
/**
* Display a combat spell's result
*/
- virtual void displaySpellResult(const InfoMessage &msg);
+ virtual void displaySpellResult(const InfoMessage &msg) = 0;
void iterateMonsters1();
void iterateMonsters2();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 9ff4f50c797..d7588122ee4 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -691,6 +691,14 @@ void Combat::setOption(SelectedOption option) {
_option = option;
}
+void Combat::displaySpellResult(const InfoMessage &msg) {
+ assert(msg._timeoutCallback || msg._keyCallback);
+ assert(!msg._delaySeconds || !msg._timeoutCallback);
+
+ // TODO: Display the spell result
+ warning("TODO: displaySpellResult");
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index e03e46683c9..6e1ebaa9a48 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -204,6 +204,8 @@ public:
Combat();
virtual ~Combat() {}
+ void displaySpellResult(const InfoMessage &msg) override;
+
/**
* Disable the flags for allowing attacks for
* the current character
Commit: 519e254764d718c94433d151e6ee1600de82d23a
https://github.com/scummvm/scummvm/commit/519e254764d718c94433d151e6ee1600de82d23a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: More wizard combat spells
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b37b57a3bc4..be6966532a1 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1090,6 +1090,24 @@ void Combat::summonLightning2() {
iterateMonsters2();
}
+void Combat::fireball2() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1 = 1;
+ ss._mmVal2 = 1;
+ ss._resistanceType = 5;
+ ss._newCondition = 0;
+
+ levelAdjust();
+}
+
+void Combat::levelAdjust() {
+ SpellsState &ss = g_globals->_spellsState;
+ for (uint i = 0; i < g_globals->_currCharacter->_level._current; ++i)
+ ss._newCondition += getRandomNumber(6);
+
+ iterateMonsters2();
+}
+
void Combat::paralyze() {
SpellsState &ss = g_globals->_spellsState;
g_globals->_combat->resetDestMonster();
@@ -1193,6 +1211,83 @@ void Combat::identifyMonster() {
displaySpellResult(msg);
}
+#undef COL2
+
+void Combat::fireball() {
+ SpellsState &ss = g_globals->_spellsState;
+
+ if (_destMonsterNum < _attackerVal) {
+ Common::String line1 = Common::String::format("|%s| %s",
+ g_globals->_currCharacter->_name,
+ STRING["spells.casts_spell"].c_str());
+
+ ss._newCondition = g_globals->_currCharacter->_level * 2 + 4;
+ ss._mmVal1++;
+ ss._mmVal2++;
+ ss._resistanceType++;
+ handlePartyDamage();
+
+ InfoMessage msg(0, 0, line1);
+ msg._delaySeconds = 3;
+ msg._timeoutCallback = []() {
+ g_globals->_combat->fireball2();
+ };
+ displaySpellResult(msg);
+ } else {
+ fireball2();
+ }
+}
+
+void Combat::lightningBolt() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._resistanceType = 3;
+ ss._mmVal2 = 2;
+
+ levelAdjust();
+}
+
+void Combat::makeRoom() {
+ for (int i = 0; i < 5; ++i)
+ _canAttack[i] = 1;
+}
+
+void Combat::slow() {
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ monsterSetPtr(i);
+ _monsterP->_speed = MAX(_monsterP->_speed / 2, 1);
+ }
+}
+
+void Combat::weaken() {
+ for (uint i = 0; i < _monsterList.size(); ++i) {
+ monsterSetPtr(i);
+ _monsterAC[i] = MAX((int)_monsterAC[i] - 1, 1);
+ }
+}
+
+bool Combat::web() {
+ SpellsState &ss = g_globals->_spellsState;
+ if (_destMonsterNum < _attackerVal)
+ return false;
+
+ ss._mmVal1++;
+ ss._mmVal2 = 0;
+ ss._resistanceType = 5;
+ ss._newCondition = UNCONSCIOUS;
+
+ iterateMonsters1();
+ return true;
+}
+
+bool Combat::acidRain() {
+ if (_attackerVal >= (int)_monsterList.size())
+ return false;
+
+ // TODO: Acid rain
+
+ return true;
+}
} // namespace Game
} // namespace MM1
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index dae234cbcdb..01ccae8a638 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -246,6 +246,8 @@ private:
void iterateMonsters2Inner();
void updateArr3();
void summonLightning2();
+ void fireball2();
+ void levelAdjust();
public:
/**
@@ -266,6 +268,13 @@ public:
// Wizard spells that need access to internal fields
void identifyMonster();
+ void fireball();
+ void lightningBolt();
+ void makeRoom();
+ void slow();
+ void weaken();
+ bool web();
+ bool acidRain();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index a2436648c31..48e3f7ca041 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -99,28 +99,28 @@ SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
wizard23_identifyMonster,
wizard24_jump,
wizard25_levitate,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
+ wizard26_power,
+ wizard27_quickness,
+ wizard28_scare,
+ wizard31_fireball,
wizard32_fly,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
- placeholder,
+ wizard33_invisibility,
+ wizard34_lightningBolt,
+ wizard35_makeRoom,
+ wizard36_slow,
+ wizard37_weaken,
+ wizard38_web,
+ wizard41_acidArrow,
+ wizard42_coldBeam,
+ wizard43_feebleMind,
+ wizard44_freeze,
wizard45_guardDog,
wizard46_psychicProtection,
- placeholder,
- placeholder,
- cleric51_deadlySwarm,
+ wizard47_shield,
+ wizard48_timeDistortion,
+ wizard51_acidRain,
wizard52_dispelMagic,
- placeholder,
+ wizard53_fingerOfDeath,
wizard54_shelter,
wizard55_teleport,
placeholder,
@@ -761,6 +761,32 @@ SpellResult SpellsParty::wizard25_levitate() {
return SR_SUCCESS_DONE;
}
+SpellResult SpellsParty::wizard26_power() {
+ g_globals->_currCharacter->_might._current += getRandomNumber(4);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard27_quickness() {
+ g_globals->_currCharacter->_speed._current += getRandomNumber(4);
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard28_scare() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._mmVal2 = 7;
+ ss._resistanceType++;
+ ss._newCondition = 1;
+
+ g_globals->_combat->iterateMonsters1();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard31_fireball() {
+ g_globals->_combat->fireball();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::wizard32_fly() {
Views::Spells::Fly::show(
[](int mapIndex) {
@@ -778,6 +804,82 @@ SpellResult SpellsParty::wizard32_fly() {
return SR_SUCCESS_SILENT;
}
+SpellResult SpellsParty::wizard33_invisibility() {
+ g_globals->_activeSpells._s.invisbility++;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard34_lightningBolt() {
+ g_globals->_combat->lightningBolt();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard35_makeRoom() {
+ g_globals->_combat->makeRoom();
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard36_slow() {
+ g_globals->_combat->slow();
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard37_weaken() {
+ g_globals->_combat->weaken();
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard38_web() {
+ return g_globals->_combat->web() ? SR_SUCCESS_SILENT : SR_FAILED;
+}
+
+SpellResult SpellsParty::wizard41_acidArrow() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._resistanceType++;
+ ss._mmVal2 = 3;
+ ss._newCondition += getRandomNumber(10) +
+ getRandomNumber(10) + getRandomNumber(10);
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard42_coldBeam() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._resistanceType++;
+ ss._mmVal2 = 4;
+
+ ss._newCondition = getRandomNumber(10) + getRandomNumber(10) +
+ getRandomNumber(10) + getRandomNumber(10);
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard43_feebleMind() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1++;
+ ss._mmVal2 = 0;
+ ss._resistanceType++;
+ ss._newCondition = 8;
+
+ g_globals->_combat->iterateMonsters1();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard44_freeze() {
+ SpellsState &ss = g_globals->_spellsState;
+ ss._mmVal1 = 0;
+ ss._mmVal2 = 6;
+ ss._resistanceType++;
+ ss._newCondition = 128;
+
+ g_globals->_combat->iterateMonsters1();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::wizard45_guardDog() {
g_globals->_activeSpells._s.guard_dog =
g_globals->_currCharacter->_level._current;
@@ -790,6 +892,25 @@ SpellResult SpellsParty::wizard46_psychicProtection() {
return SR_SUCCESS_DONE;
}
+SpellResult SpellsParty::wizard47_shield() {
+ g_globals->_activeSpells._s.shield++;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard48_timeDistortion() {
+ // TODO: time distortion
+ return SR_FAILED;
+}
+
+SpellResult SpellsParty::wizard51_acidRain() {
+ return g_globals->_combat->acidRain() ? SR_SUCCESS_SILENT : SR_FAILED;
+}
+
+SpellResult SpellsParty::wizard53_fingerOfDeath() {
+ // TODO: finger of death
+ return SR_FAILED;
+}
+
SpellResult SpellsParty::wizard54_shelter() {
if (g_maps->_currentState & 8)
return SR_FAILED;
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index f0697b184a2..242d11c68e0 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -138,12 +138,30 @@ private:
static SpellResult wizard23_identifyMonster();
static SpellResult wizard24_jump();
static SpellResult wizard25_levitate();
+ static SpellResult wizard26_power();
+ static SpellResult wizard27_quickness();
+ static SpellResult wizard28_scare();
+ static SpellResult wizard31_fireball();
static SpellResult wizard32_fly();
+ static SpellResult wizard33_invisibility();
+ static SpellResult wizard34_lightningBolt();
+ static SpellResult wizard35_makeRoom();
+ static SpellResult wizard36_slow();
+ static SpellResult wizard37_weaken();
+ static SpellResult wizard38_web();
+ static SpellResult wizard41_acidArrow();
+ static SpellResult wizard42_coldBeam();
+ static SpellResult wizard43_feebleMind();
+ static SpellResult wizard44_freeze();
static SpellResult wizard45_guardDog();
static SpellResult wizard46_psychicProtection();
+ static SpellResult wizard47_shield();
+ static SpellResult wizard48_timeDistortion();
+ static SpellResult wizard51_acidRain();
static SpellResult wizard52_dispelMagic() {
return cleric52_dispelMagic();
}
+ static SpellResult wizard53_fingerOfDeath();
static SpellResult wizard54_shelter();
static SpellResult wizard55_teleport();
static SpellResult wizard63_etherialize();
Commit: 732762a5978a8163e39bbd4c266b5620cd4d82bf
https://github.com/scummvm/scummvm/commit/732762a5978a8163e39bbd4c266b5620cd4d82bf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: More wizard spells implemented
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/spells_party.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 2e0c837cd16..8871ca6a550 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -828,6 +828,7 @@ spells:
8: "IS TURNED TO STONE"
9: "IS ERADICATED"
10: "IS AFFECTED"
+ disintegrated: "IS DISINTEGRATED!"
monster_effects:
0: "IS SCARED"
1: "IS BLINDED"
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index be6966532a1..bcb67b29967 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1036,7 +1036,7 @@ void Combat::turnUndead() {
if ((monster->_resistUndead & IS_UNDEAD) &&
(getRandomNumber(20) + g_globals->_currCharacter->_level) >=
(_monsterHP[i] * 2 + 10)) {
- destroyUndead();
+ destroyMonster();
++_monstersDestroyedCtr;
}
}
@@ -1050,7 +1050,7 @@ void Combat::turnUndead() {
_arr3[_currentChar] = 1;
}
-void Combat::destroyUndead() {
+void Combat::destroyMonster() {
_monsterStatus[getMonsterIndex()] = 0xff;
Sound::sound2(SOUND_9);
}
@@ -1150,7 +1150,7 @@ void Combat::holyWord() {
for (uint i = 0; i < _monsterList.size(); ++i) {
monsterSetPtr(i);
if (_monsterP->_resistUndead & IS_UNDEAD) {
- destroyUndead();
+ destroyMonster();
++_monstersDestroyedCtr;
}
}
@@ -1260,10 +1260,17 @@ void Combat::slow() {
}
void Combat::weaken() {
+ SpellsState &ss = g_globals->_spellsState;
+
for (uint i = 0; i < _monsterList.size(); ++i) {
monsterSetPtr(i);
_monsterAC[i] = MAX((int)_monsterAC[i] - 1, 1);
}
+
+ resetDestMonster();
+ ss._mmVal1++;
+ ss._newCondition = 2;
+ iterateMonsters2();
}
bool Combat::web() {
@@ -1281,14 +1288,89 @@ bool Combat::web() {
}
bool Combat::acidRain() {
+ SpellsState &ss = g_globals->_spellsState;
if (_attackerVal >= (int)_monsterList.size())
return false;
- // TODO: Acid rain
+ _destMonsterNum = _attackerVal;
+ monsterSetPtr(_destMonsterNum);
+ monsterIndexOf();
+
+ ss._mmVal1 = 1;
+ ss._mmVal2 = 3;
+ ss._resistanceType = 15;
+ ss._newCondition = 0;
+
+ for (int i = 0; i < 5; ++i)
+ ss._newCondition += getRandomNumber(10);
+ iterateMonsters2();
return true;
}
+void Combat::fingerOfDeath() {
+ Common::String line1 = Common::String::format("|%s| %s",
+ g_globals->_currCharacter->_name,
+ STRING["spells.casts_spell"].c_str());
+
+ const Common::String monsterName = _monsterP->_name;
+ bool kills = !(_monsterP->_resistUndead & IS_UNDEAD) &&
+ !monsterLevelThreshold();
+ if (kills) {
+ proc2();
+ kills = !_val9;
+
+ if (kills)
+ destroyMonster();
+ }
+ removeMonster();
+
+ Common::String line2 = Common::String::format("|%s| %s",
+ kills ? STRING["spells.char_effects.7"].c_str() :
+ STRING["monster_spells.not_affected"].c_str()
+ );
+
+ InfoMessage msg(0, 0, line1, 0, 2, line2);
+ msg._delaySeconds = 3;
+ msg._timeoutCallback = []() {
+ g_globals->_combat->_arr3[g_globals->_combat->_currentChar] = 1;
+ g_globals->_combat->combatLoop();
+ };
+
+ displaySpellResult(msg);
+}
+
+void Combat::disintegration() {
+ Common::String line1 = Common::String::format("|%s| %s",
+ g_globals->_currCharacter->_name,
+ STRING["spells.casts_spell"].c_str());
+
+ const Common::String monsterName = _monsterP->_name;
+ bool kills = !monsterLevelThreshold();
+ if (kills) {
+ proc2();
+ kills = !_val9;
+
+ if (kills)
+ destroyMonster();
+ }
+ removeMonster();
+
+ Common::String line2 = Common::String::format("|%s| %s",
+ kills ? STRING["spells.char_effects.disintegrated"].c_str() :
+ STRING["monster_spells.not_affected"].c_str()
+ );
+
+ InfoMessage msg(0, 0, line1, 0, 2, line2);
+ msg._delaySeconds = 3;
+ msg._timeoutCallback = []() {
+ g_globals->_combat->_arr3[g_globals->_combat->_currentChar] = 1;
+ g_globals->_combat->combatLoop();
+ };
+
+ displaySpellResult(msg);
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 01ccae8a638..015e5876784 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -240,7 +240,7 @@ protected:
private:
void spellFailed();
- void destroyUndead();
+ void destroyMonster();
bool monsterLevelThreshold() const;
void iterateMonsters1Inner();
void iterateMonsters2Inner();
@@ -275,6 +275,8 @@ public:
void weaken();
bool web();
bool acidRain();
+ void fingerOfDeath();
+ void disintegration();
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index 48e3f7ca041..b48c514f751 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -123,16 +123,16 @@ SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
wizard53_fingerOfDeath,
wizard54_shelter,
wizard55_teleport,
- placeholder,
- placeholder,
+ wizard61_dancingSword,
+ wizard62_disintegration,
wizard63_etherialize,
wizard64_protectionFromMagic,
wizard65_rechargeItem,
wizard71_astralSpell,
wizard72_duplication,
- placeholder,
- placeholder,
- placeholder,
+ wizard73_meteorShower,
+ wizard74_powerShield,
+ wizard75_prismaticLight
};
byte FLY_MAP_ID1[20] = {
@@ -826,7 +826,7 @@ SpellResult SpellsParty::wizard36_slow() {
SpellResult SpellsParty::wizard37_weaken() {
g_globals->_combat->weaken();
- return SR_SUCCESS_DONE;
+ return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard38_web() {
@@ -907,8 +907,8 @@ SpellResult SpellsParty::wizard51_acidRain() {
}
SpellResult SpellsParty::wizard53_fingerOfDeath() {
- // TODO: finger of death
- return SR_FAILED;
+ g_globals->_combat->fingerOfDeath();
+ return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard54_shelter() {
@@ -924,6 +924,23 @@ SpellResult SpellsParty::wizard55_teleport() {
return SR_SUCCESS_SILENT;
}
+SpellResult SpellsParty::wizard61_dancingSword() {
+ SpellsState &ss = g_globals->_spellsState;
+ g_globals->_combat->resetDestMonster();
+
+ ss._mmVal1 = 0;
+ ss._mmVal2 = 0;
+ ss._newCondition = getRandomNumber(30);
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard62_disintegration() {
+ g_globals->_combat->disintegration();
+ return SR_SUCCESS_SILENT;
+}
+
SpellResult SpellsParty::wizard63_etherialize() {
g_events->draw();
g_maps->_currentState = 0;
@@ -952,9 +969,49 @@ SpellResult SpellsParty::wizard71_astralSpell() {
}
SpellResult SpellsParty::wizard72_duplication() {
+ // TODO: Implement duplication
return SR_FAILED;
}
+SpellResult SpellsParty::wizard73_meteorShower() {
+ SpellsState &ss = g_globals->_spellsState;
+ g_globals->_combat->resetDestMonster();
+
+ ss._mmVal1++;
+ ss._mmVal2 = 5;
+ ss._newCondition = MIN((int)getRandomNumber(120) +
+ (int)g_globals->_currCharacter->_level._current, 120);
+
+ g_globals->_combat->iterateMonsters2();
+ return SR_SUCCESS_SILENT;
+}
+
+SpellResult SpellsParty::wizard74_powerShield() {
+ g_globals->_activeSpells._s.power_shield++;
+ return SR_SUCCESS_DONE;
+}
+
+SpellResult SpellsParty::wizard75_prismaticLight() {
+ SpellsState &ss = g_globals->_spellsState;
+ g_globals->_combat->resetDestMonster();
+
+ if (getRandomNumber(100) < 20)
+ return SR_FAILED;
+
+ if (ss._mmVal1 < 50) {
+ uint count = getRandomNumber(4);
+ ss._newCondition <<= count;
+ g_globals->_combat->iterateMonsters2();
+
+ } else {
+ uint count = getRandomNumber(8);
+ ss._newCondition <<= count;
+ g_globals->_combat->iterateMonsters1();
+ }
+
+ return SR_SUCCESS_SILENT;
+}
+
void SpellsParty::restoreHp(uint16 hp) {
restoreHp(*_destChar, hp);
}
diff --git a/engines/mm/mm1/game/spells_party.h b/engines/mm/mm1/game/spells_party.h
index 242d11c68e0..ec50673d2f2 100644
--- a/engines/mm/mm1/game/spells_party.h
+++ b/engines/mm/mm1/game/spells_party.h
@@ -68,9 +68,6 @@ private:
static void display(const InfoMessage &msg);
private:
- static SpellResult placeholder() {
- return SR_FAILED;
- }
static SpellResult cleric11_awaken();
static SpellResult cleric12_bless();
static SpellResult cleric13_blind();
@@ -164,11 +161,16 @@ private:
static SpellResult wizard53_fingerOfDeath();
static SpellResult wizard54_shelter();
static SpellResult wizard55_teleport();
+ static SpellResult wizard61_dancingSword();
+ static SpellResult wizard62_disintegration();
static SpellResult wizard63_etherialize();
static SpellResult wizard64_protectionFromMagic();
static SpellResult wizard65_rechargeItem();
static SpellResult wizard71_astralSpell();
static SpellResult wizard72_duplication();
+ static SpellResult wizard73_meteorShower();
+ static SpellResult wizard74_powerShield();
+ static SpellResult wizard75_prismaticLight();
static SpellFn SPELLS[SPELLS_COUNT];
public:
Commit: 69dc6043d1d9f4d31226b1badfac97fd3ec92918
https://github.com/scummvm/scummvm/commit/69dc6043d1d9f4d31226b1badfac97fd3ec92918
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:37+01:00
Commit Message:
MM: MM1: Hook up duplication spell to it's custom view
Changed paths:
engines/mm/mm1/game/spells_party.cpp
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index b48c514f751..c3066dce805 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -969,8 +969,8 @@ SpellResult SpellsParty::wizard71_astralSpell() {
}
SpellResult SpellsParty::wizard72_duplication() {
- // TODO: Implement duplication
- return SR_FAILED;
+ g_events->addView("Duplication");
+ return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard73_meteorShower() {
Commit: 22f4b8af8460353d72f6da433d404df1d336eaca
https://github.com/scummvm/scummvm/commit/22f4b8af8460353d72f6da433d404df1d336eaca
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:38+01:00
Commit Message:
MM: MM1: Finished search view
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/character.cpp
engines/mm/mm1/data/character.h
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/treasure.cpp
engines/mm/mm1/data/treasure.h
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/sound.h
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/search.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 8871ca6a550..be6c8edb0c2 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -168,6 +168,11 @@
magic_trap: "MAGIC (%c) TRAP (%c)"
who_will_try: "WHO WILL TRY '1'-'%c'"
check_condition: "*** CHECK CONDITION ***"
+ it_opens: "IT OPENS!"
+ receives: "RECEIVES"
+ each_share: "EACH SHARE IS WORTH %d GOLD"
+ found_gems: "%s FOUND %d GEMS"
+ found_item: "%s FOUND %s"
statues:
stone: "ON THIS STONE STATUE OF "
plaque: "A PLAQUE READS..."
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 7888d90a42e..09c2e202365 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -593,6 +593,10 @@ bool Character::hasItem(byte itemId) const {
_equipped.indexOf(itemId) != -1;
}
+Common::String Character::getDisplayName() const {
+ return Common::String::format("|%s|", _name);
+}
+
#define PERF16(x) ((x & 0xff) + ((x >> 8) & 0xff))
#define PERF32(x) ((x & 0xff) + ((x >> 8) & 0xff) + \
((x >> 16) & 0xff) + ((x >> 24) & 0xff))
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 6398455a3e5..f2b8bfed448 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -527,6 +527,11 @@ struct Character : public PrimaryAttributes {
*/
bool hasItem(byte itemId) const;
+ /**
+ * Return a display version of the character's name
+ */
+ Common::String getDisplayName() const;
+
/**
* Gets the numeric value of every property a character
* has and totals it up to give a stupid 'performance'
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index aee1b863a42..d32bdff582a 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -116,8 +116,7 @@ bool Party::checkPartyDead() const {
if (isPartyDead()) {
// At this point, there's no good characters.
// So redirect to the death screen
- g_events->clearViews();
- g_events->addView("Dead");
+ g_events->replaceView("Dead", true);
return true;
} else {
return false;
diff --git a/engines/mm/mm1/data/treasure.cpp b/engines/mm/mm1/data/treasure.cpp
index 5d159fc5239..a92ff40b3ea 100644
--- a/engines/mm/mm1/data/treasure.cpp
+++ b/engines/mm/mm1/data/treasure.cpp
@@ -38,6 +38,7 @@ byte &Treasure::operator[](uint i) {
}
bool Treasure::present() const {
+ // Checks for items, treasure, and/or gems
for (int i = 0; i < TREASURE_COUNT; ++i) {
if (_data[i + 3])
return true;
@@ -46,6 +47,27 @@ bool Treasure::present() const {
return false;
}
+bool Treasure::hasItems() const {
+ for (int i = 0; i < 3; ++i) {
+ if (_items[i])
+ return true;
+ }
+
+ return false;
+}
+
+byte Treasure::getItem() {
+ for (int i = 0; i < 3; ++i) {
+ if (_items[i]) {
+ byte result = _items[i];
+ _items[i] = 0;
+ return result;
+ }
+ }
+
+ return 0;
+}
+
void Treasure::synchronize(Common::Serializer &s) {
s.syncBytes(_data, 9);
}
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
index fbf4cad7873..a7821dbd4cb 100644
--- a/engines/mm/mm1/data/treasure.h
+++ b/engines/mm/mm1/data/treasure.h
@@ -41,6 +41,7 @@ private:
public:
byte &_trapType = _data[1];
byte &_container = _data[2];
+ byte *const _items = &_data[3];
Treasure() {
clear();
@@ -58,10 +59,48 @@ public:
*/
bool present() const;
+ /**
+ * Returns true if any items are present
+ */
+ bool hasItems() const;
+
/**
* Synchronize savegame data
*/
void synchronize(Common::Serializer &s);
+
+ /**
+ * Return the gold value for the treasure
+ */
+ uint16 getGold() const {
+ return READ_LE_UINT16(&_data[6]);
+ }
+
+ /**
+ * Sets the gold value for the treasure
+ */
+ void setGold(uint16 amount) {
+ WRITE_LE_UINT16(&_data[6], amount);
+ }
+
+ /**
+ * Return the gems amount
+ */
+ byte getGems() const {
+ return _data[8];
+ }
+
+ /**
+ * Set the gems amount
+ */
+ void setGems(byte amount) {
+ _data[8] = amount;
+ }
+
+ /**
+ * Get any item, and remove it from the treasure
+ */
+ byte getItem();
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index c3066dce805..f793206951b 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -898,8 +898,14 @@ SpellResult SpellsParty::wizard47_shield() {
}
SpellResult SpellsParty::wizard48_timeDistortion() {
- // TODO: time distortion
- return SR_FAILED;
+ Maps::Map &map = *g_maps->_currentMap;
+
+ if (getRandomNumber(100) < map[Maps::MAP_DISPEL_THRESHOLD])
+ return SR_FAILED;
+
+ // End combat by closing the combat view
+ g_events->focusedView()->close();
+ return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard51_acidRain() {
diff --git a/engines/mm/mm1/sound.h b/engines/mm/mm1/sound.h
index 1adeeb0ff11..2c29e51e9c5 100644
--- a/engines/mm/mm1/sound.h
+++ b/engines/mm/mm1/sound.h
@@ -26,8 +26,8 @@ namespace MM {
namespace MM1 {
enum SoundId {
- SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3, SOUND_4 = 4, SOUND_8 = 8,
- SOUND_9 = 9
+ SOUND_1 = 1, SOUND_2 = 2, SOUND_3 = 3, SOUND_4 = 4,
+ SOUND_5 = 5, SOUND_8 = 8, SOUND_9 = 9
};
class Sound {
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index bb06aab38f9..c300b33bf0b 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -51,13 +51,26 @@ bool Search::msgGame(const GameMessage &msg) {
}
bool Search::msgFocus(const FocusMessage &msg) {
- _mode = INITIAL;
+ _bounds = getLineBounds(20, 24);
+ _lineNum = 0;
+
+ if (_mode == FOCUS_GET_TREASURE) {
+ // Returning from trap display
+ if (g_globals->_party.checkPartyDead())
+ return true;
+
+ getTreasure();
+ } else {
+ _mode = INITIAL;
+ }
+
return true;
}
void Search::draw() {
Common::String line;
- clearSurface();
+ if (_mode != GET_ITEMS)
+ clearSurface();
switch (_mode) {
case INITIAL:
@@ -75,6 +88,15 @@ void Search::draw() {
escToGoBack(0, 3);
break;
+ case GET_TREASURE:
+ drawTreasure();
+ break;
+
+ case GET_ITEMS:
+ // This may be called up to three times, for each item
+ drawItem();
+ break;
+
default:
break;
}
@@ -135,6 +157,12 @@ bool Search::msgKeypress(const KeypressMessage &msg) {
}
}
break;
+
+ case GET_TREASURE:
+
+
+ default:
+ break;
}
return true;
@@ -174,6 +202,19 @@ void Search::timeout() {
draw();
break;
+ case GET_TREASURE:
+ _mode = GET_ITEMS;
+ draw();
+ break;
+
+ case GET_ITEMS:
+ draw();
+ break;
+
+ case GET_ITEMS_DONE:
+ close();
+ break;
+
default:
break;
}
@@ -186,7 +227,19 @@ void Search::openContainer() {
}
void Search::openContainer2() {
+ if (g_globals->_treasure._trapType == 1) {
+ Maps::Map &map = *g_maps->_currentMap;
+ int thresold = map[Maps::MAP_TRAP_THRESHOLD] +
+ g_globals->_treasure._container;
+ if (getRandomNumber(thresold + 5) < thresold) {
+ // Triggered a trap
+ g_events->send("Trap", GameMessage("TRAP"));
+ return;
+ }
+ }
+
+ getTreasure();
}
void Search::findRemoveTrap() {
@@ -201,7 +254,9 @@ void Search::findRemoveTrap2() {
if (g_globals->_treasure._trapType == 1) {
byte val = c._trapCtr;
if (getRandomNumber(val >= 100 ? val + 5 : 100) >= val) {
- // TODO
+ // Triggered a trap
+ g_events->send("Trap", GameMessage("TRAP"));
+ return;
}
}
}
@@ -249,6 +304,101 @@ bool Search::whoWillTry() {
}
}
+void Search::getTreasure() {
+ _mode = GET_TREASURE;
+ _bounds = getLineBounds(17, 24);
+
+ // Display a graphic for the container type
+ int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 3 : 1;
+ send("View", DrawGraphicMessage(gfxNum + 65));
+
+ uint gems = g_globals->_treasure.getGems();
+ if (gems) {
+
+ }
+
+ draw();
+}
+
+void Search::drawTreasure() {
+ writeString(15, 0, STRING["dialogs.search.it_opens"]);
+
+ // Split up the gold across the party
+ uint32 goldPerPerson = g_globals->_treasure.getGold() /
+ g_globals->_party.size();
+ g_globals->_treasure.setGold(0);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ uint32 newGold = c._gold + goldPerPerson;
+ if (newGold < c._gold)
+ // As unlikely as it to overflow 32-bits
+ newGold = 0xffffffff;
+ c._gold = newGold;
+ }
+
+ writeString(0, 2, Common::String::format(
+ STRING["dialogs.search.each_share"].c_str(),
+ goldPerPerson));
+ g_globals->_treasure.setGold(0);
+
+ // Assign any gems to a random person
+ int gems = g_globals->_treasure.getGems();
+ g_globals->_treasure.setGems(0);
+
+ _lineNum = 3;
+ if (gems) {
+ // Choose a random recipient
+ uint charNum = getRandomNumber(g_globals->_party.size()) - 1;
+ Character &c = g_globals->_party[charNum];
+
+ writeString(0, _lineNum++, Common::String::format(
+ STRING["dialogs.search.found_gems"].c_str(),
+ c.getDisplayName().c_str(),
+ gems));
+ c._gems = MIN((int)c._gems + gems, 0xffff);
+ }
+
+ Sound::sound2(SOUND_5);
+ delaySeconds(2);
+}
+
+void Search::drawItem() {
+ Treasure &treasure = g_globals->_treasure;
+ int itemId = treasure.getItem();
+
+ // Iterate through any treasure items
+ if (itemId != 0) {
+ // Find a person with free backpack space for the item
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+
+ // Check if character has backpack space
+ if (c._backpack.full())
+ continue;
+
+ Item *item = g_globals->_items.getItem(itemId);
+ c._backpack.add(itemId, item->_maxCharges);
+
+ // Add line for found item
+ writeString(0, _lineNum++, Common::String::format(
+ STRING["dialogs.search.found_item"].c_str(),
+ c.getDisplayName().c_str(),
+ item->_name.c_str()
+ ));
+
+ delaySeconds(2);
+ return;
+ }
+ }
+
+ // At this point we've either displayed the up to 3 item
+ // lines (in addition to gold and/or gems), or the party's
+ // backpacks were completely full up. Wait for 7 seconds
+ _mode = GET_ITEMS_DONE;
+ delaySeconds(7);
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/search.h b/engines/mm/mm1/views/search.h
index c8c26789abe..6c18b6cd2d4 100644
--- a/engines/mm/mm1/views/search.h
+++ b/engines/mm/mm1/views/search.h
@@ -30,10 +30,15 @@ namespace Views {
class Search : public TextView {
private:
- enum Mode { INITIAL, OPTIONS, RESPONSE, WHO_WILL_TRY };
+ enum Mode {
+ INITIAL, OPTIONS, RESPONSE, WHO_WILL_TRY,
+ FOCUS_GET_TREASURE, GET_TREASURE, GET_ITEMS,
+ GET_ITEMS_DONE
+ };
Mode _mode = INITIAL;
bool _removing = false;
byte _val1 = 0;
+ int _lineNum = 0;
/**
* Open the container
@@ -52,8 +57,26 @@ private:
*/
void detectMagicTrap();
+ /**
+ * Select which user to try and remove trap or detect magic
+ */
bool whoWillTry();
+ /**
+ * Finally give the treasure
+ */
+ void getTreasure();
+
+ /**
+ * Draw the treasure result
+ */
+ void drawTreasure();
+
+ /**
+ * Get any treasure items
+ */
+ void drawItem();
+
public:
Search();
virtual ~Search() {}
Commit: 896a6ae9ddf77d5c227dbdcd741d858a1b0be37f
https://github.com/scummvm/scummvm/commit/896a6ae9ddf77d5c227dbdcd741d858a1b0be37f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:38+01:00
Commit Message:
MM: MM1: Improve map classes setting of treasure
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map06.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map13.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map22.cpp
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/maps/map28.cpp
engines/mm/mm1/maps/map31.cpp
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map42.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map53.cpp
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/maps/ghost.cpp
engines/mm/mm1/views/maps/ice_princess.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index bcb67b29967..c1d3cf07764 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -338,15 +338,14 @@ void Combat::proc1() {
if (_val7 & 6) {
if (!(_val7 & 2)) {
- WRITE_LE_UINT16(&g_globals->_treasure[6],
- READ_LE_UINT16(&g_globals->_treasure[6]) +
+ g_globals->_treasure.setGold(g_globals->_treasure.getGold() +
getRandomNumber(10));
} else if (!(_val7 & 4)) {
- WRITE_LE_UINT16(&g_globals->_treasure[6],
- READ_LE_UINT16(&g_globals->_treasure[6]) +
+ g_globals->_treasure.setGold(g_globals->_treasure.getGold() +
getRandomNumber(100));
} else {
- g_globals->_treasure[7] += getRandomNumber(4);
+ g_globals->_treasure.setGold(g_globals->_treasure.getGold() +
+ getRandomNumber(4) * 256);
}
}
}
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 6e1b42245ee..82f3caa91f4 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -147,8 +147,8 @@ void Map03::special07() {
void Map03::special08() {
g_globals->_treasure._container = GOLD_CHEST;
- g_globals->_treasure[5] = 200;
- g_globals->_treasure[8] = 200;
+ g_globals->_treasure._items[2] = 200;
+ g_globals->_treasure.setGems(200);
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index d3a2b673c77..5ac7a7b2d92 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -52,9 +52,8 @@ void Map04::special() {
g_maps->clearSpecial();
if ((*g_maps->_currentMap)[MAP04_TREASURE_STOLEN] < 255)
(*g_maps->_currentMap)[MAP04_TREASURE_STOLEN]++;
- g_globals->_treasure[6] = 88;
- g_globals->_treasure[7] = 2;
- g_globals->_treasure[8] = 10;
+ g_globals->_treasure.setGold(600);
+ g_globals->_treasure.setGems(10);
g_events->addAction(KEYBIND_SEARCH);
}
));
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
index 3fc5eb99760..20fc20df081 100644
--- a/engines/mm/mm1/maps/map06.cpp
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -195,10 +195,9 @@ void Map06::special26() {
if (_data[VAL3]) {
send(SoundMessage(STRING["maps.map06.wizard"]));
} else {
- g_globals->_treasure[6] = 224;
- g_globals->_treasure[7] = 46;
- g_globals->_treasure[4] = 237;
- g_globals->_treasure[5] = getRandomNumber(12) + 182;
+ g_globals->_treasure.setGold(12000);
+ g_globals->_treasure._items[1] = BRONZE_KEY_ID;
+ g_globals->_treasure._items[2] = getRandomNumber(12) + 182;
g_events->addAction(KEYBIND_SEARCH);
}
}
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 9077b4cbf16..c732df44137 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -191,8 +191,8 @@ void Map07::special16() {
void Map07::special17() {
poolYN([]() {
- g_globals->_treasure[5] = getRandomNumber(12) + 24;
- g_globals->_treasure[8] = 20;
+ g_globals->_treasure._items[2] = getRandomNumber(12) + 24;
+ g_globals->_treasure.setGems(20);
g_events->addAction(KEYBIND_SEARCH);
});
}
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 968ab833bc5..c35681c22f2 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -115,15 +115,15 @@ void Map08::special08() {
void Map08::special20() {
g_maps->clearSpecial();
- g_globals->_treasure[5] = getRandomNumber(48);
- g_globals->_treasure[1] = 1;
+ g_globals->_treasure._items[2] = getRandomNumber(48);
+ g_globals->_treasure._trapType = 1;
g_globals->_treasure._container = SILVER_BOX;
addTreasure();
}
void Map08::addTreasure() {
- g_globals->_treasure[6] = getRandomNumber(150) + 100;
- g_globals->_treasure[8] = getRandomNumber(4);
+ g_globals->_treasure.setGold(getRandomNumber(150) + 100);
+ g_globals->_treasure.setGems(getRandomNumber(4));
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index 4bef007ab10..4dfa8a32c80 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -126,8 +126,8 @@ void Map09::special08() {
0, 2, STRING["maps.map09.shrine2"]
));
- g_globals->_treasure[5] = getRandomNumber(26) + 120;
- g_globals->_treasure[6] = 120;
+ g_globals->_treasure._items[2] = getRandomNumber(26) + 120;
+ g_globals->_treasure.setGold(120);
g_events->addAction(KEYBIND_SEARCH);
} else {
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index 39356bc5c58..37ff30060a6 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -120,8 +120,8 @@ void Map10::special19() {
void Map10::special20() {
g_maps->clearSpecial();
- g_globals->_treasure[5] = 252;
- g_globals->_treasure[8] = 20;
+ g_globals->_treasure._items[2] = 252;
+ g_globals->_treasure.setGems(20);
g_globals->_treasure._container = SILVER_CHEST;
g_events->addAction(KEYBIND_SEARCH);
}
@@ -165,7 +165,7 @@ void Map10::special29() {
void Map10::special30() {
Game::Encounter &enc = g_globals->_encounters;
int monsterCount = getRandomNumber(4) + 3;
- g_globals->_treasure[5] = 252;
+ g_globals->_treasure._items[2] = 252;
enc.clearMonsters();
for (int i = 0; i < monsterCount; ++i)
@@ -183,7 +183,7 @@ void Map10::special31() {
void Map10::special32() {
Game::Encounter &enc = g_globals->_encounters;
int monsterCount = getRandomNumber(4) + 3;
- g_globals->_treasure[5] = 243;
+ g_globals->_treasure._items[2] = 243;
enc.clearMonsters();
for (int i = 0; i < monsterCount; ++i)
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 75ebde78403..011bffc5037 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -48,7 +48,7 @@ void Map11::special() {
}
}
- g_globals->_treasure[5] = 0;
+ g_globals->_treasure._items[2] = 0;
if (getRandomNumber(50) == 10) {
pit();
diff --git a/engines/mm/mm1/maps/map13.cpp b/engines/mm/mm1/maps/map13.cpp
index d251c31c963..69103b57f32 100644
--- a/engines/mm/mm1/maps/map13.cpp
+++ b/engines/mm/mm1/maps/map13.cpp
@@ -88,7 +88,7 @@ void Map13::special00() {
void Map13::special01() {
if (_data[VAL1]) {
g_maps->clearSpecial();
- g_globals->_treasure[5] = 246;
+ g_globals->_treasure._items[2] = 246;
g_events->addAction(KEYBIND_SEARCH);
} else {
_data[VAL1]++;
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index 2bd9811908f..8decba12a8c 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -32,7 +32,7 @@ namespace Maps {
#define VAL1 350
#define VAL2 118
#define VAL3 361
-#define VAL4 362
+#define GEMS 362
void Map15::special() {
Game::Encounter &enc = g_globals->_encounters;
@@ -105,7 +105,7 @@ void Map15::special01() {
if (_data[VAL2]) {
send(SoundMessage(STRING["maps.map15.dragon"]));
- g_globals->_treasure[5] = 244;
+ g_globals->_treasure._items[2] = 244;
g_events->addAction(KEYBIND_SEARCH);
} else {
@@ -149,13 +149,13 @@ void Map15::special03() {
void Map15::special04() {
_data[VAL3] = 250;
- _data[VAL4] = 100;
+ _data[GEMS] = 100;
cove();
}
void Map15::special05() {
_data[VAL3] = 251;
- _data[VAL4] = 200;
+ _data[GEMS] = 200;
cove();
}
@@ -165,7 +165,7 @@ void Map15::special06() {
[](const Common::KeyState &ks) {
if (ks.keycode == Common::KEYCODE_y) {
g_events->close();
- g_globals->_treasure[5] = 233;
+ g_globals->_treasure._items[2] = 233;
g_events->addAction(KEYBIND_SEARCH);
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->send(SoundMessage(STRING["maps.map15.percella1"]));
@@ -192,9 +192,8 @@ void Map15::cove() {
int idx = c._backpack.indexOf(map[VAL3]);
if (idx != -1) {
c._backpack.removeAt(idx);
- g_globals->_treasure[8] = map[VAL4];
- g_globals->_treasure[7] = 7;
- g_globals->_treasure[6] = 208;
+ g_globals->_treasure.setGold(2000);
+ g_globals->_treasure.setGems(map[GEMS]);
break;
}
}
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 3c0693b8b88..1b698d9a0ba 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -88,7 +88,7 @@ void Map17::special01() {
void Map17::special02() {
if (_data[VAL3]) {
- g_globals->_treasure[5] = 236;
+ g_globals->_treasure._items[2] = 236;
g_events->addAction(KEYBIND_SEARCH);
} else {
g_events->addKeypress((Common::KeyCode)211);
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index b3843258e87..fa4330f5bc9 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -163,11 +163,10 @@ void Map18::special08() {
void Map18::special09() {
g_maps->clearSpecial();
- g_globals->_treasure[5] = 238;
- g_globals->_treasure[1] = 4;
+ g_globals->_treasure._items[2] = 238;
+ g_globals->_treasure._trapType = 4;
g_globals->_treasure._container = IRON_BOX;
- g_globals->_treasure[6] = 96;
- g_globals->_treasure[7] = 9;
+ g_globals->_treasure.setGold(2400);
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map22.cpp b/engines/mm/mm1/maps/map22.cpp
index 36b55ca4b3b..319b3030848 100644
--- a/engines/mm/mm1/maps/map22.cpp
+++ b/engines/mm/mm1/maps/map22.cpp
@@ -106,7 +106,7 @@ void Map22::special02() {
[]() {
g_maps->clearSpecial();
if (g_maps->_mapPos.x == 5) {
- g_globals->_treasure[5] = 234;
+ g_globals->_treasure._items[2] = 234;
g_events->addAction(KEYBIND_SEARCH);
} else {
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index b50a162236d..7d63f667098 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -181,10 +181,10 @@ void Map23::special12() {
void Map23::special13() {
g_maps->clearSpecial();
g_globals->_treasure._container = IRON_BOX;
- g_globals->_treasure[3] = 171;
- g_globals->_treasure[4] = 183;
- g_globals->_treasure[5] = 191;
- g_globals->_treasure[6] = 12;
+ g_globals->_treasure._items[0] = 171;
+ g_globals->_treasure._items[1] = 183;
+ g_globals->_treasure._items[2] = 191;
+ g_globals->_treasure.setGold(12);
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index fc84d228f85..78d54eb482c 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -129,7 +129,7 @@ void Map25::special() {
g_globals->_currCharacter->_flags[7] |= CHARFLAG7_10;
}
- g_globals->_treasure[8] = 20;
+ g_globals->_treasure.setGems(20);
} else {
g_globals->_activeSpells._s.cursed = 10;
g_globals->_encounters.execute();
diff --git a/engines/mm/mm1/maps/map28.cpp b/engines/mm/mm1/maps/map28.cpp
index 8b4e91f2840..30395878e90 100644
--- a/engines/mm/mm1/maps/map28.cpp
+++ b/engines/mm/mm1/maps/map28.cpp
@@ -146,21 +146,21 @@ void Map28::special00() {
switch (ks.keycode) {
case Common::KEYCODE_a:
g_events->close();
- g_globals->_treasure[7] = getRandomNumber(8) + 8;
+ g_globals->_treasure.setGold((getRandomNumber(8) + 8) * 256);
g_maps->clearSpecial();
g_events->addAction(KEYBIND_SEARCH);
break;
case Common::KEYCODE_b:
g_events->close();
- g_globals->_treasure[8] = getRandomNumber(50) + 200;
+ g_globals->_treasure.setGems(getRandomNumber(50) + 200);
g_maps->clearSpecial();
g_events->addAction(KEYBIND_SEARCH);
break;
case Common::KEYCODE_c:
g_events->close();
- g_globals->_treasure[5] = getRandomNumber(22) + 196;
+ g_globals->_treasure._items[2] = getRandomNumber(22) + 196;
g_maps->clearSpecial();
g_events->addAction(KEYBIND_SEARCH);
break;
diff --git a/engines/mm/mm1/maps/map31.cpp b/engines/mm/mm1/maps/map31.cpp
index fd3c2add92d..e835fb3e026 100644
--- a/engines/mm/mm1/maps/map31.cpp
+++ b/engines/mm/mm1/maps/map31.cpp
@@ -92,7 +92,7 @@ void Map31::special02() {
void Map31::special06() {
if (_data[VAL1]) {
- g_globals->_treasure[5] = 243;
+ g_globals->_treasure._items[2] = 243;
g_events->addAction(KEYBIND_SEARCH);
} else {
none160();
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index 4c8bfcf2a92..77a480b4d6b 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -172,7 +172,7 @@ void Map33::special04() {
STRING["maps.map33.corpse"],
[]() {
g_events->send(SoundMessage(STRING["maps.map33.thanks"]));
- g_globals->_treasure[8] = 50;
+ g_globals->_treasure.setGems(50);
g_events->addAction(KEYBIND_SEARCH);
}
));
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 8edac8894d9..1e9b2908904 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -103,7 +103,7 @@ void Map35::special05() {
void Map35::special06() {
g_maps->clearSpecial();
- g_globals->_treasure[8] = 30;
+ g_globals->_treasure.setGems(30);
g_events->addAction(KEYBIND_SEARCH);
}
@@ -115,7 +115,7 @@ void Map35::special07() {
void Map35::special09() {
g_maps->clearSpecial();
- g_globals->_treasure[8] = 50;
+ g_globals->_treasure.setGems(50);
special07();
}
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index 98884b3760f..4f7e232f42b 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -113,7 +113,7 @@ void Map36::special07() {
}
void Map36::special11() {
- g_globals->_treasure[8] = 30;
+ g_globals->_treasure.setGems(30);
special07();
}
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index de7920e3db8..4fc01d4e3e4 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -155,14 +155,14 @@ void Map37::special15() {
send(SoundMessage(STRING["maps.wall_painted"]));
if (!g_globals->_party.hasItem(B_QUEEN_IDOL_ID)) {
- g_globals->_treasure[5] = B_QUEEN_IDOL_ID;
+ g_globals->_treasure._items[2] = B_QUEEN_IDOL_ID;
}
}
void Map37::special16() {
g_maps->clearSpecial();
g_globals->_treasure._container = GOLD_BOX;
- g_globals->_treasure[8] = 100;
+ g_globals->_treasure.setGems(100);
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
index 3d432b1e888..20a07cb5c59 100644
--- a/engines/mm/mm1/maps/map42.cpp
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -145,8 +145,7 @@ void Map42::special15() {
}
void Map42::special17() {
- g_globals->_treasure[6] = 76;
- g_globals->_treasure[7] = 29;
+ g_globals->_treasure.setGold(7500);
g_globals->_treasure._container = GOLD_BOX;
g_events->addAction(KEYBIND_SEARCH);
}
@@ -158,8 +157,8 @@ void Map42::dogSuccess() {
c._exp += 10000;
}
- g_globals->_treasure[5] = GOLD_KEY_ID;
- g_globals->_treasure[1] = 2;
+ g_globals->_treasure._items[2] = GOLD_KEY_ID;
+ g_globals->_treasure._trapType = 2;
none160();
}
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 822616a21de..129e633a009 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -111,8 +111,7 @@ void Map43::special05() {
void Map43::special06() {
if (_data[VAL1]) {
- g_globals->_treasure[6] = 80;
- g_globals->_treasure[7] = 70;
+ g_globals->_treasure.setGold(18000);
g_maps->clearSpecial();
g_events->addAction(KEYBIND_SEARCH);
} else {
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index 4e4d1bb8ba3..bc9c51fa1f7 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -141,8 +141,7 @@ void Map49::special16() {
}
void Map49::special20() {
- g_globals->_treasure[7] = 46;
- g_globals->_treasure[6] = 224;
+ g_globals->_treasure.setGold(12000);
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/maps/map53.cpp b/engines/mm/mm1/maps/map53.cpp
index 621bcc86b2c..c6bef03b414 100644
--- a/engines/mm/mm1/maps/map53.cpp
+++ b/engines/mm/mm1/maps/map53.cpp
@@ -54,7 +54,7 @@ void Map53::special() {
void Map53::special00() {
send(SoundMessage(STRING["maps.wall_painted"]));
if (!_data[VAL1]) {
- g_globals->_treasure[5] = W_QUEEN_IDOL_ID;
+ g_globals->_treasure._items[2] = W_QUEEN_IDOL_ID;
_data[VAL1]++;
}
}
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 465b1393f08..e19200ba9e5 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -64,7 +64,7 @@ bool Game::msgAction(const ActionMessage &msg) {
g_events->send(GameMessage("REST"));
return true;
case KEYBIND_SEARCH:
- g_globals->_treasure[5] = 240; //***DEBUG***
+ g_globals->_treasure._items[2] = 240; //***DEBUG***
send("Search", GameMessage("SHOW"));
break;
case KEYBIND_UNLOCK:
diff --git a/engines/mm/mm1/views/maps/ghost.cpp b/engines/mm/mm1/views/maps/ghost.cpp
index 473f24eb879..2c25d54825e 100644
--- a/engines/mm/mm1/views/maps/ghost.cpp
+++ b/engines/mm/mm1/views/maps/ghost.cpp
@@ -56,7 +56,7 @@ bool Ghost::msgKeypress(const KeypressMessage &msg) {
}
close();
- g_globals->_treasure[5] = RING_OF_OKRIM_ID;
+ g_globals->_treasure._items[2] = RING_OF_OKRIM_ID;
g_events->addAction(KEYBIND_SEARCH);
}
diff --git a/engines/mm/mm1/views/maps/ice_princess.cpp b/engines/mm/mm1/views/maps/ice_princess.cpp
index 03a9cff4ef3..488afd827a8 100644
--- a/engines/mm/mm1/views/maps/ice_princess.cpp
+++ b/engines/mm/mm1/views/maps/ice_princess.cpp
@@ -61,13 +61,13 @@ void IcePrincess::answerEntered() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
g_globals->_currCharacter = &g_globals->_party[i];
if (g_globals->_currCharacter->_backpack.indexOf(DIAMOND_KEY_ID) != -1) {
- g_globals->_treasure[5] = 237;
+ g_globals->_treasure._items[2] = 237;
g_events->addAction(KEYBIND_SEARCH);
return;
}
}
- g_globals->_treasure[5] = 240;
+ g_globals->_treasure._items[2] = 240;
g_events->addAction(KEYBIND_SEARCH);
}
);
Commit: c9cc2d56cf7f8a2b463b482b05902a2abbdd1f5e
https://github.com/scummvm/scummvm/commit/c9cc2d56cf7f8a2b463b482b05902a2abbdd1f5e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:38+01:00
Commit Message:
MM: MM1: Further treasure cleanups
Changed paths:
engines/mm/mm1/data/treasure.cpp
engines/mm/mm1/data/treasure.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/views/search.cpp
diff --git a/engines/mm/mm1/data/treasure.cpp b/engines/mm/mm1/data/treasure.cpp
index a92ff40b3ea..63b38aeb769 100644
--- a/engines/mm/mm1/data/treasure.cpp
+++ b/engines/mm/mm1/data/treasure.cpp
@@ -56,7 +56,7 @@ bool Treasure::hasItems() const {
return false;
}
-byte Treasure::getItem() {
+byte Treasure::removeItem() {
for (int i = 0; i < 3; ++i) {
if (_items[i]) {
byte result = _items[i];
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
index a7821dbd4cb..0a54dc7d488 100644
--- a/engines/mm/mm1/data/treasure.h
+++ b/engines/mm/mm1/data/treasure.h
@@ -100,7 +100,7 @@ public:
/**
* Get any item, and remove it from the treasure
*/
- byte getItem();
+ byte removeItem();
};
} // namespace MM1
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index c1d3cf07764..39f9bd1c8f9 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -397,12 +397,12 @@ void Combat::selectTreasure2(int count) {
_val1 += getRandomNumber(_allowFight) - 1;
auto &treasure = g_globals->_treasure;
- if (!treasure[3])
- treasure[3] = _val1;
- else if (!treasure[4])
- treasure[4] = _val1;
- else if (!treasure[5])
- treasure[5] = _val1;
+ if (!treasure._items[0])
+ treasure._items[0] = _val1;
+ else if (!treasure._items[1])
+ treasure._items[1] = _val1;
+ else if (!treasure._items[2])
+ treasure._items[2] = _val1;
}
void Combat::nextRound() {
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index c300b33bf0b..57055fe4256 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -175,8 +175,8 @@ void Search::timeout() {
_val1 = MIN(g_globals->_treasure._container * 8 +
map[Maps::MAP_TRAP_THRESHOLD], 255);
- if (!g_globals->_treasure[1]) {
- g_globals->_treasure[1] = (getRandomNumber(100) < _val1) ? 1 : 2;
+ if (!g_globals->_treasure._trapType) {
+ g_globals->_treasure._trapType = (getRandomNumber(100) < _val1) ? 1 : 2;
}
// Show the name of the container type in the game view
@@ -279,8 +279,8 @@ void Search::detectMagicTrap() {
} else {
c._sp._current--;
- char magic = g_globals->_treasure[3] || g_globals->_treasure[4]
- || g_globals->_treasure[5] || g_globals->_treasure[8] ? 'Y' : 'N';
+ char magic = g_globals->_treasure.hasItems() ||
+ g_globals->_treasure.getGems() ? 'Y' : 'N';
char trapped = g_globals->_treasure._trapType == 1 ? 'Y' : 'N';
clearSurface();
@@ -365,7 +365,7 @@ void Search::drawTreasure() {
void Search::drawItem() {
Treasure &treasure = g_globals->_treasure;
- int itemId = treasure.getItem();
+ int itemId = treasure.removeItem();
// Iterate through any treasure items
if (itemId != 0) {
Commit: 06c3754b7be70163d6faa984e7f4a25b2ab814b8
https://github.com/scummvm/scummvm/commit/06c3754b7be70163d6faa984e7f4a25b2ab814b8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:38+01:00
Commit Message:
MM: MM1: Add MonsterActions base class for monster actions logic
Changed paths:
A engines/mm/mm1/game/monster_actions.cpp
A engines/mm/mm1/game/monster_actions.h
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.h
engines/mm/module.mk
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index be6c8edb0c2..3202b5cf44e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -887,6 +887,28 @@ monster_spells:
energy: "ENERGY"
swarm: "SWARM"
breathes: "BREATHES "
+monster_actions:
+ and: "!AND "
+ causes_aging: "CAUSES RAPID AGING"
+ causes_blindness: "CAUSES BLINDNESS"
+ causes_paralysis: "CAUSES PARALYSIS"
+ drains_ability: "DRAINS ABILITY"
+ drains_lifeforce: "DRAINS LIFEFORCE"
+ drains_might: "DRAINS MIGHT"
+ drains_sp: "DRAINS SPELL POINTS"
+ induces_poison: "INDUCES POISON"
+ induces_sleep: "INDUCES SLEEP"
+ induces_unconsciousness: "INDUCES UNCONSCIOUSNESS"
+ inflicts_disease: "INFLICTS DISEASE"
+ is_eradicated: "IS ERADICATED"
+ is_killed: "IS KILLED"
+ reduces_endurance: "REDUCES ENDURANCE"
+ steals_gems: "STEALS SOME GEMS"
+ steals_gold: "STEALS SOME GOLD"
+ steals_gold_and_gems: "STEALS GOLD AND GEMS"
+ steals_something: "STEALS SOMETHING"
+ takes_food: "TAKES FOOD"
+ turned_to_stone: "IS TURNED TO STONE"
maps:
poof: "POOF!"
sign: "A SIGN ABOVE THE DOOR READS:\n"
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 015e5876784..f9a0f8f700c 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -27,13 +27,13 @@
#include "mm/mm1/data/party.h"
#include "mm/mm1/game/game_logic.h"
#include "mm/mm1/game/encounter.h"
-#include "mm/mm1/game/spells_monsters.h"
+#include "mm/mm1/game/monster_actions.h"
namespace MM {
namespace MM1 {
namespace Game {
-class Combat : public SpellsMonsters {
+class Combat : public MonsterActions {
protected:
Common::Array<Monster> &_monsterList;
Common::Array<Line> _message;
diff --git a/engines/mm/mm1/game/monster_actions.cpp b/engines/mm/mm1/game/monster_actions.cpp
new file mode 100644
index 00000000000..65f06352d11
--- /dev/null
+++ b/engines/mm/mm1/game/monster_actions.cpp
@@ -0,0 +1,388 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/game/monster_actions.h"
+#include "mm/mm1/maps/maps.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+const MonsterActionsAction MonsterActions::ACTIONS[25] = {
+ &MonsterActions::action00,
+ &MonsterActions::action01,
+ &MonsterActions::action02,
+ &MonsterActions::action03,
+ &MonsterActions::action04,
+ &MonsterActions::action05,
+ &MonsterActions::action06,
+ &MonsterActions::action07,
+ &MonsterActions::action08,
+ &MonsterActions::action09,
+ &MonsterActions::action10,
+ &MonsterActions::action11,
+ &MonsterActions::action12,
+ &MonsterActions::action13,
+ &MonsterActions::action14,
+ &MonsterActions::action15,
+ &MonsterActions::action16,
+ &MonsterActions::action17,
+ &MonsterActions::action18,
+ &MonsterActions::action19,
+ &MonsterActions::action20,
+ &MonsterActions::action21,
+ &MonsterActions::action22,
+ &MonsterActions::action23,
+ &MonsterActions::action24
+};
+
+#define LINE(ACTION) line = Common::String::format(" %s%s", \
+ STRING["monster_actions.and"].c_str(), STRING[ACTION].c_str())
+
+bool MonsterActions::monsterAction(uint index, Common::String &line) {
+ line = "";
+ return (this->*ACTIONS[index])(line);
+}
+
+bool MonsterActions::canPerform(int level) const {
+ return getRandomNumber(level) == level;
+}
+
+bool MonsterActions::action00(Common::String &line) {
+ if (canPerform(3)) {
+ g_globals->_currCharacter->_food = 0;
+ LINE("monster_actions.takes_food");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action01(Common::String &line) {
+ if (canPerform(20)) {
+ setCondition(DISEASED);
+ LINE("monster_actions.inflicts_disease");
+ return true;
+ }
+
+ return true;
+}
+
+bool MonsterActions::action02(Common::String &line) {
+ if (canPerform(20)) {
+ return action07(line);
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action03(Common::String &line) {
+ if (canPerform(20)) {
+ return action11(line);
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action04(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (canPerform(2) && c._gems != 0) {
+ c._gems /= 2;
+ LINE("monster_actions.steals_gems");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action05(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (c._endurance._current == 0 || --c._endurance._current == 0)
+ setCondition(BAD_CONDITION | DEAD);
+ _damage += 3;
+
+ LINE("monster_actions.reduces_endurance");
+ return true;
+}
+
+bool MonsterActions::action06(Common::String &line) {
+ if (damageType7()) {
+ setCondition(ASLEEP);
+ LINE("monster_actions.induces_sleep");
+ return true;
+ }
+
+ return false;
+}
+
+bool MonsterActions::action07(Common::String &line) {
+ if (damageType5()) {
+ setCondition(3);
+ LINE("monster_actions.cures_paralysis");
+ return true;
+ }
+
+ return false;
+}
+
+bool MonsterActions::action08(Common::String &line) {
+ if (canPerform(4)) {
+ setCondition(DISEASED);
+ LINE("monster_actions.inflicts_disease");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action09(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (canPerform(2) && c._gold != 0) {
+ c._gold /= 2;
+ LINE("monster_actions.steals_gold");
+ return true;
+
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool MonsterActions::action10(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (canPerform(2) && !c._backpack.empty()) {
+ c._backpack.removeAt(c._backpack.size() - 1);
+ LINE("monster_actions.steals_something");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action11(Common::String &line) {
+ if (damageType6()) {
+ setCondition(16);
+ LINE("monster_actions.induces_poison");
+ return true;
+ }
+
+ return false;
+}
+
+bool MonsterActions::action12(Common::String &line) {
+ if (canPerform(3)) {
+ setCondition(BLINDED);
+ LINE("monster_actions.causes_blindness");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action13(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (c._level._current == 0 || --c._level._current == 0)
+ setCondition(BAD_CONDITION | DEAD);
+
+ _damage += 10;
+ LINE("monster_actions.drains_lifeforce");
+ return true;
+}
+
+bool MonsterActions::action14(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (canPerform(3) && isCharAffected()) {
+ setCondition(BAD_CONDITION | STONE);
+ line = Common::String::format("%s %s",
+ c.getDisplayName().c_str(),
+ STRING["monster_actions.turned_to_stone"].c_str()
+ );
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action15(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (isCharAffected()) {
+ int age = c._age._base + 10;
+ c._age._base = age;
+
+ if (age > 255) {
+ c._age._base = 200;
+ setCondition(ERADICATED);
+ }
+
+ LINE("monster_actions.causes_aging");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action16(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (c._level < 3) {
+ c._level._current = 0;
+ setCondition(BAD_CONDITION | DEAD);
+
+ } else {
+ c._level._current -= 2;
+ }
+
+ _damage += 20;
+ LINE("monster_actions.drains_lifeforce");
+ return true;
+}
+
+bool MonsterActions::action17(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (canPerform(3) && isCharAffected()) {
+ setCondition(BAD_CONDITION | DEAD);
+ line = Common::String::format("%s %s",
+ c.getDisplayName().c_str(),
+ STRING["monster_actions.is_killed"].c_str()
+ );
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action18(Common::String &line) {
+ if (canPerform(3) && isCharAffected()) {
+ setCondition(UNCONSCIOUS);
+ LINE("monster_actions.induces_unconsciousness");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action19(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (c._might._current < 4) {
+ c._might._current = 0;
+ setCondition(BAD_CONDITION | DEAD);
+
+ } else {
+ c._might._current -= 3;
+ }
+
+ LINE("monster_actions.drains_might");
+ return true;
+}
+
+bool MonsterActions::action20(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ for (int i = 0; i < 7; ++i) {
+ AttributePair &attr = c.getAttribute(i);
+
+ if (attr._current < 3) {
+ attr._current = 0;
+ setCondition(BAD_CONDITION | DEAD);
+
+ } else {
+ attr._current -= 2;
+ }
+ }
+
+ LINE("monster_actions.drains_abilities");
+ return true;
+}
+
+bool MonsterActions::action21(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (canPerform(2)) {
+ c._backpack.clear();
+ LINE("monster_actions.steals_backpack");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action22(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ if (canPerform(2)) {
+ c._gold = 0;
+ c._gems = 0;
+
+ LINE("monster_actions.steals_gold_and_gems");
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+bool MonsterActions::action23(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ setCondition(ERADICATED);
+ line = Common::String::format("%s %s",
+ c.getDisplayName().c_str(),
+ STRING["monster_actions.is_eradicated"].c_str()
+ );
+
+ return true;
+}
+
+bool MonsterActions::action24(Common::String &line) {
+ Character &c = *g_globals->_currCharacter;
+
+ c._sp._current = 0;
+ LINE("monster_actions.drains_sp");
+ return true;
+}
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/monster_actions.h b/engines/mm/mm1/game/monster_actions.h
new file mode 100644
index 00000000000..10e34b17764
--- /dev/null
+++ b/engines/mm/mm1/game/monster_actions.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_GAME_MONSTER_ACTIONS
+#define MM1_GAME_MONSTER_ACTIONS
+
+#include "mm/mm1/game/spells_monsters.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+class MonsterActions;
+typedef bool (MonsterActions:: *MonsterActionsAction)(Common::String &line);
+
+class MonsterActions : public SpellsMonsters {
+private:
+ static const MonsterActionsAction ACTIONS[25];
+
+ bool canPerform(int level) const;
+private:
+ bool action00(Common::String &line);
+ bool action01(Common::String &line);
+ bool action02(Common::String &line);
+ bool action03(Common::String &line);
+ bool action04(Common::String &line);
+ bool action05(Common::String &line);
+ bool action06(Common::String &line);
+ bool action07(Common::String &line);
+ bool action08(Common::String &line);
+ bool action09(Common::String &line);
+ bool action10(Common::String &line);
+ bool action11(Common::String &line);
+ bool action12(Common::String &line);
+ bool action13(Common::String &line);
+ bool action14(Common::String &line);
+ bool action15(Common::String &line);
+ bool action16(Common::String &line);
+ bool action17(Common::String &line);
+ bool action18(Common::String &line);
+ bool action19(Common::String &line);
+ bool action20(Common::String &line);
+ bool action21(Common::String &line);
+ bool action22(Common::String &line);
+ bool action23(Common::String &line);
+ bool action24(Common::String &line);
+
+public:
+ virtual ~MonsterActions() {}
+
+ bool monsterAction(uint index, Common::String &line);
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index d5cb1061f8c..a04bf1b2798 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -118,11 +118,6 @@ private:
*/
bool charAffected();
- /**
- * Returns true if character is affected so spell
- */
- bool isCharAffected() const;
-
/**
* Checks random range
*/
@@ -146,17 +141,6 @@ private:
bool testElementalResistance();
- /**
- * Test whether character resists different damage types
- */
- bool damageType1();
- bool damageType2();
- bool damageType3();
- bool damageType4();
- bool damageType5();
- bool damageType6();
- bool damageType7();
-
/**
* Adds different spell effects to the lines
*/
@@ -167,7 +151,6 @@ private:
*/
void handlePartyEffects();
- void setCondition(byte newCondition);
void proc9();
protected:
@@ -185,6 +168,27 @@ protected:
*/
void handlePartyDamage();
+ /**
+ * Sets the condition to apply
+ */
+ void setCondition(byte newCondition);
+
+ /**
+ * Returns true if character is affected so spell
+ */
+ bool isCharAffected() const;
+
+ /**
+ * Test whether character resists different damage types
+ */
+ bool damageType1();
+ bool damageType2();
+ bool damageType3();
+ bool damageType4();
+ bool damageType5();
+ bool damageType6();
+ bool damageType7();
+
public:
SpellsMonsters();
virtual ~SpellsMonsters() {}
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index e44ebe79cb8..b89b6c401ee 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -28,6 +28,7 @@ MODULE_OBJS := \
mm1/game/game_logic.o \
mm1/game/combat.o \
mm1/game/encounter.o \
+ mm1/game/monster_actions.o \
mm1/game/rest.o \
mm1/game/spell_casting.o \
mm1/game/spells_party.o \
Commit: 11959696037b7cb0b1a765ce5548b8fc190dc582
https://github.com/scummvm/scummvm/commit/11959696037b7cb0b1a765ce5548b8fc190dc582
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:38+01:00
Commit Message:
MM: MM1: Rename MonsterActions class to MonsterTouch
The actions are triggered by monsters with a "bonus on touch".
So MonsterTouch is more appropriate than MonsterActions
Changed paths:
A engines/mm/mm1/game/monster_touch.cpp
A engines/mm/mm1/game/monster_touch.h
R engines/mm/mm1/game/monster_actions.cpp
R engines/mm/mm1/game/monster_actions.h
engines/mm/mm1/game/combat.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index f9a0f8f700c..dd282081066 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -27,13 +27,13 @@
#include "mm/mm1/data/party.h"
#include "mm/mm1/game/game_logic.h"
#include "mm/mm1/game/encounter.h"
-#include "mm/mm1/game/monster_actions.h"
+#include "mm/mm1/game/monster_touch.h"
namespace MM {
namespace MM1 {
namespace Game {
-class Combat : public MonsterActions {
+class Combat : public MonsterTouch {
protected:
Common::Array<Monster> &_monsterList;
Common::Array<Line> _message;
diff --git a/engines/mm/mm1/game/monster_actions.cpp b/engines/mm/mm1/game/monster_touch.cpp
similarity index 72%
rename from engines/mm/mm1/game/monster_actions.cpp
rename to engines/mm/mm1/game/monster_touch.cpp
index 65f06352d11..6d8ad6d2800 100644
--- a/engines/mm/mm1/game/monster_actions.cpp
+++ b/engines/mm/mm1/game/monster_touch.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "mm/mm1/game/monster_actions.h"
+#include "mm/mm1/game/monster_touch.h"
#include "mm/mm1/maps/maps.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/sound.h"
@@ -28,47 +28,47 @@ namespace MM {
namespace MM1 {
namespace Game {
-const MonsterActionsAction MonsterActions::ACTIONS[25] = {
- &MonsterActions::action00,
- &MonsterActions::action01,
- &MonsterActions::action02,
- &MonsterActions::action03,
- &MonsterActions::action04,
- &MonsterActions::action05,
- &MonsterActions::action06,
- &MonsterActions::action07,
- &MonsterActions::action08,
- &MonsterActions::action09,
- &MonsterActions::action10,
- &MonsterActions::action11,
- &MonsterActions::action12,
- &MonsterActions::action13,
- &MonsterActions::action14,
- &MonsterActions::action15,
- &MonsterActions::action16,
- &MonsterActions::action17,
- &MonsterActions::action18,
- &MonsterActions::action19,
- &MonsterActions::action20,
- &MonsterActions::action21,
- &MonsterActions::action22,
- &MonsterActions::action23,
- &MonsterActions::action24
+const MonsterTouchAction MonsterTouch::ACTIONS[25] = {
+ &MonsterTouch::action00,
+ &MonsterTouch::action01,
+ &MonsterTouch::action02,
+ &MonsterTouch::action03,
+ &MonsterTouch::action04,
+ &MonsterTouch::action05,
+ &MonsterTouch::action06,
+ &MonsterTouch::action07,
+ &MonsterTouch::action08,
+ &MonsterTouch::action09,
+ &MonsterTouch::action10,
+ &MonsterTouch::action11,
+ &MonsterTouch::action12,
+ &MonsterTouch::action13,
+ &MonsterTouch::action14,
+ &MonsterTouch::action15,
+ &MonsterTouch::action16,
+ &MonsterTouch::action17,
+ &MonsterTouch::action18,
+ &MonsterTouch::action19,
+ &MonsterTouch::action20,
+ &MonsterTouch::action21,
+ &MonsterTouch::action22,
+ &MonsterTouch::action23,
+ &MonsterTouch::action24
};
#define LINE(ACTION) line = Common::String::format(" %s%s", \
STRING["monster_actions.and"].c_str(), STRING[ACTION].c_str())
-bool MonsterActions::monsterAction(uint index, Common::String &line) {
+bool MonsterTouch::monsterTouch(uint index, Common::String &line) {
line = "";
return (this->*ACTIONS[index])(line);
}
-bool MonsterActions::canPerform(int level) const {
+bool MonsterTouch::canPerform(int level) const {
return getRandomNumber(level) == level;
}
-bool MonsterActions::action00(Common::String &line) {
+bool MonsterTouch::action00(Common::String &line) {
if (canPerform(3)) {
g_globals->_currCharacter->_food = 0;
LINE("monster_actions.takes_food");
@@ -79,7 +79,7 @@ bool MonsterActions::action00(Common::String &line) {
}
}
-bool MonsterActions::action01(Common::String &line) {
+bool MonsterTouch::action01(Common::String &line) {
if (canPerform(20)) {
setCondition(DISEASED);
LINE("monster_actions.inflicts_disease");
@@ -89,7 +89,7 @@ bool MonsterActions::action01(Common::String &line) {
return true;
}
-bool MonsterActions::action02(Common::String &line) {
+bool MonsterTouch::action02(Common::String &line) {
if (canPerform(20)) {
return action07(line);
@@ -98,7 +98,7 @@ bool MonsterActions::action02(Common::String &line) {
}
}
-bool MonsterActions::action03(Common::String &line) {
+bool MonsterTouch::action03(Common::String &line) {
if (canPerform(20)) {
return action11(line);
@@ -107,7 +107,7 @@ bool MonsterActions::action03(Common::String &line) {
}
}
-bool MonsterActions::action04(Common::String &line) {
+bool MonsterTouch::action04(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (canPerform(2) && c._gems != 0) {
@@ -120,7 +120,7 @@ bool MonsterActions::action04(Common::String &line) {
}
}
-bool MonsterActions::action05(Common::String &line) {
+bool MonsterTouch::action05(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (c._endurance._current == 0 || --c._endurance._current == 0)
@@ -131,7 +131,7 @@ bool MonsterActions::action05(Common::String &line) {
return true;
}
-bool MonsterActions::action06(Common::String &line) {
+bool MonsterTouch::action06(Common::String &line) {
if (damageType7()) {
setCondition(ASLEEP);
LINE("monster_actions.induces_sleep");
@@ -141,7 +141,7 @@ bool MonsterActions::action06(Common::String &line) {
return false;
}
-bool MonsterActions::action07(Common::String &line) {
+bool MonsterTouch::action07(Common::String &line) {
if (damageType5()) {
setCondition(3);
LINE("monster_actions.cures_paralysis");
@@ -151,7 +151,7 @@ bool MonsterActions::action07(Common::String &line) {
return false;
}
-bool MonsterActions::action08(Common::String &line) {
+bool MonsterTouch::action08(Common::String &line) {
if (canPerform(4)) {
setCondition(DISEASED);
LINE("monster_actions.inflicts_disease");
@@ -162,7 +162,7 @@ bool MonsterActions::action08(Common::String &line) {
}
}
-bool MonsterActions::action09(Common::String &line) {
+bool MonsterTouch::action09(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (canPerform(2) && c._gold != 0) {
@@ -177,7 +177,7 @@ bool MonsterActions::action09(Common::String &line) {
return true;
}
-bool MonsterActions::action10(Common::String &line) {
+bool MonsterTouch::action10(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (canPerform(2) && !c._backpack.empty()) {
@@ -190,7 +190,7 @@ bool MonsterActions::action10(Common::String &line) {
}
}
-bool MonsterActions::action11(Common::String &line) {
+bool MonsterTouch::action11(Common::String &line) {
if (damageType6()) {
setCondition(16);
LINE("monster_actions.induces_poison");
@@ -200,7 +200,7 @@ bool MonsterActions::action11(Common::String &line) {
return false;
}
-bool MonsterActions::action12(Common::String &line) {
+bool MonsterTouch::action12(Common::String &line) {
if (canPerform(3)) {
setCondition(BLINDED);
LINE("monster_actions.causes_blindness");
@@ -211,7 +211,7 @@ bool MonsterActions::action12(Common::String &line) {
}
}
-bool MonsterActions::action13(Common::String &line) {
+bool MonsterTouch::action13(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (c._level._current == 0 || --c._level._current == 0)
@@ -222,7 +222,7 @@ bool MonsterActions::action13(Common::String &line) {
return true;
}
-bool MonsterActions::action14(Common::String &line) {
+bool MonsterTouch::action14(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (canPerform(3) && isCharAffected()) {
@@ -238,7 +238,7 @@ bool MonsterActions::action14(Common::String &line) {
}
}
-bool MonsterActions::action15(Common::String &line) {
+bool MonsterTouch::action15(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (isCharAffected()) {
@@ -258,7 +258,7 @@ bool MonsterActions::action15(Common::String &line) {
}
}
-bool MonsterActions::action16(Common::String &line) {
+bool MonsterTouch::action16(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (c._level < 3) {
@@ -274,7 +274,7 @@ bool MonsterActions::action16(Common::String &line) {
return true;
}
-bool MonsterActions::action17(Common::String &line) {
+bool MonsterTouch::action17(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (canPerform(3) && isCharAffected()) {
@@ -290,7 +290,7 @@ bool MonsterActions::action17(Common::String &line) {
}
}
-bool MonsterActions::action18(Common::String &line) {
+bool MonsterTouch::action18(Common::String &line) {
if (canPerform(3) && isCharAffected()) {
setCondition(UNCONSCIOUS);
LINE("monster_actions.induces_unconsciousness");
@@ -301,7 +301,7 @@ bool MonsterActions::action18(Common::String &line) {
}
}
-bool MonsterActions::action19(Common::String &line) {
+bool MonsterTouch::action19(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (c._might._current < 4) {
@@ -316,7 +316,7 @@ bool MonsterActions::action19(Common::String &line) {
return true;
}
-bool MonsterActions::action20(Common::String &line) {
+bool MonsterTouch::action20(Common::String &line) {
Character &c = *g_globals->_currCharacter;
for (int i = 0; i < 7; ++i) {
@@ -335,7 +335,7 @@ bool MonsterActions::action20(Common::String &line) {
return true;
}
-bool MonsterActions::action21(Common::String &line) {
+bool MonsterTouch::action21(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (canPerform(2)) {
@@ -348,7 +348,7 @@ bool MonsterActions::action21(Common::String &line) {
}
}
-bool MonsterActions::action22(Common::String &line) {
+bool MonsterTouch::action22(Common::String &line) {
Character &c = *g_globals->_currCharacter;
if (canPerform(2)) {
@@ -363,7 +363,7 @@ bool MonsterActions::action22(Common::String &line) {
}
}
-bool MonsterActions::action23(Common::String &line) {
+bool MonsterTouch::action23(Common::String &line) {
Character &c = *g_globals->_currCharacter;
setCondition(ERADICATED);
@@ -375,7 +375,7 @@ bool MonsterActions::action23(Common::String &line) {
return true;
}
-bool MonsterActions::action24(Common::String &line) {
+bool MonsterTouch::action24(Common::String &line) {
Character &c = *g_globals->_currCharacter;
c._sp._current = 0;
diff --git a/engines/mm/mm1/game/monster_actions.h b/engines/mm/mm1/game/monster_touch.h
similarity index 85%
rename from engines/mm/mm1/game/monster_actions.h
rename to engines/mm/mm1/game/monster_touch.h
index 10e34b17764..8bb410a4b2c 100644
--- a/engines/mm/mm1/game/monster_actions.h
+++ b/engines/mm/mm1/game/monster_touch.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef MM1_GAME_MONSTER_ACTIONS
-#define MM1_GAME_MONSTER_ACTIONS
+#ifndef MM1_GAME_MONSTER_TOUCH_H
+#define MM1_GAME_MONSTER_TOUCH_H
#include "mm/mm1/game/spells_monsters.h"
@@ -28,12 +28,12 @@ namespace MM {
namespace MM1 {
namespace Game {
-class MonsterActions;
-typedef bool (MonsterActions:: *MonsterActionsAction)(Common::String &line);
+class MonsterTouch;
+typedef bool (MonsterTouch::*MonsterTouchAction)(Common::String &line);
-class MonsterActions : public SpellsMonsters {
+class MonsterTouch : public SpellsMonsters {
private:
- static const MonsterActionsAction ACTIONS[25];
+ static const MonsterTouchAction ACTIONS[25];
bool canPerform(int level) const;
private:
@@ -64,9 +64,9 @@ private:
bool action24(Common::String &line);
public:
- virtual ~MonsterActions() {}
+ virtual ~MonsterTouch() {}
- bool monsterAction(uint index, Common::String &line);
+ bool monsterTouch(uint index, Common::String &line);
};
} // namespace Game
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b89b6c401ee..7973da7c867 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -28,7 +28,7 @@ MODULE_OBJS := \
mm1/game/game_logic.o \
mm1/game/combat.o \
mm1/game/encounter.o \
- mm1/game/monster_actions.o \
+ mm1/game/monster_touch.o \
mm1/game/rest.o \
mm1/game/spell_casting.o \
mm1/game/spells_party.o \
Commit: 95929db968c6ba3e0b945f3922abcc6f11a70e52
https://github.com/scummvm/scummvm/commit/95929db968c6ba3e0b945f3922abcc6f11a70e52
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:38+01:00
Commit Message:
MM: MM1: Monster touch interface method in Combat class
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 39f9bd1c8f9..9ada74e1057 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -830,6 +830,22 @@ void Combat::updateMonsterStatus() {
}
}
+bool Combat::monsterTouch(Common::String &line) {
+ line.clear();
+
+ if (_val10 || !_monsterP->_bonusOnTouch)
+ return false;
+ if (_monsterP->_bonusOnTouch & 0x80) {
+ proc9();
+ // Original returned value, but caller didn't use.
+ // So for ScummVM we return true only if an action is done
+ //return g_globals->_spellsState._mmVal7;
+ return false;
+ }
+
+ return MonsterTouch::monsterTouch(_monsterP->_bonusOnTouch, line);
+}
+
void Combat::iterateMonsters1() {
_spellMonsterCount = _monsterList.size();
iterateMonsters1Inner();
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index dd282081066..06fd71226b4 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -238,6 +238,11 @@ protected:
*/
void updateMonsterStatus();
+ /**
+ * Handles a monster touch action, if any
+ */
+ bool monsterTouch(Common::String &line);
+
private:
void spellFailed();
void destroyMonster();
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index a04bf1b2798..9604dc6941c 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -151,8 +151,6 @@ private:
*/
void handlePartyEffects();
- void proc9();
-
protected:
byte _arr1[MAX_COMBAT_MONSTERS];
byte _monsterStatus[MAX_COMBAT_MONSTERS];
@@ -189,6 +187,8 @@ protected:
bool damageType6();
bool damageType7();
+ void proc9();
+
public:
SpellsMonsters();
virtual ~SpellsMonsters() {}
Commit: b259ed6b2bf9a2f3be95f92b65f0b9777f1a8712
https://github.com/scummvm/scummvm/commit/b259ed6b2bf9a2f3be95f92b65f0b9777f1a8712
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:38+01:00
Commit Message:
MM: MM1: In progress monster attack logic
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/messages.cpp
engines/mm/mm1/messages.h
engines/mm/mm1/views/combat.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3202b5cf44e..14863d5bafa 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -399,7 +399,22 @@
7: "(AFRAID) "
8: "(DEAD) "
wounded: "(WOUNDED) "
-
+ attack_types:
+ 0: "ATTACKS"
+ 1: "FIGHTS"
+ 2: "CHARGES"
+ 3: "ASSAULTS"
+ 4: "BATTLES"
+ 5: "STABS AT"
+ 6: "FLAILS AT"
+ 7: "LUNGES AT"
+ 8: "SWINGS AT"
+ 9: "CHOPS AT"
+ 10: "HACKS AT"
+ 11: "THRUSTS AT"
+ 12: "SLASHES AT"
+ 13: "STRIKES AT"
+ 14: "THRASHES AT"
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 9ada74e1057..63255b29160 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -50,7 +50,7 @@ void Combat::clear() {
_val1 = 0;
_val6 = _val7 = 0;
_val8 = _val9 = _val10 = 0;
- _val11 = 0;
+ _destAC = 0;
_numberOfTimes = 0;
_attackerLevel = 0;
_advanceIndex = 0;
@@ -789,8 +789,8 @@ void Combat::attackMonster(int monsterNum) {
}
if (g_globals->_activeSpells._s.cursed) {
- if (++_val11 > 255)
- _val11 = 200;
+ if (++_destAC > 255)
+ _destAC = 200;
}
addAttackDamage();
@@ -807,11 +807,11 @@ void Combat::attackMonster(int monsterNum) {
void Combat::addAttackDamage() {
_damage = 0;
_timesHit = 0;
- _val11 += 10;
+ _destAC += 10;
for (int i = 0; i < _numberOfTimes; ++i) {
int val = getRandomNumber(20);
- if (val == 20 || (val != 1 && (val + _attackerLevel) >= _val11)) {
+ if (val == 20 || (val != 1 && (val + _attackerLevel) >= _destAC)) {
_damage = MAX(_damage + (int)_attackAttr2._current +
getRandomNumber(_attackAttr2._base), 255);
++_timesHit;
@@ -1386,6 +1386,103 @@ void Combat::disintegration() {
displaySpellResult(msg);
}
+void Combat::monsterAttack(InfoMessage &msg) {
+ int styleNum = getRandomNumber(
+ (msg._lines.back().size() < 13) ? 15 : 11);
+ Common::String attackStyle = STRING[Common::String::format(
+ "dialogs.combat.attack_types.%d", styleNum)];
+ _val10 = 0;
+
+ msg._lines.back()._text += attackStyle;
+ monsterAttack2(msg);
+}
+
+void Combat::monsterAttack2(InfoMessage &msg) {
+ Character &c = *g_globals->_currCharacter;
+
+ // Add the destination character being attacked
+ msg._lines.back()._text += ' ';
+ msg._lines.back()._text += c.getDisplayName();
+
+ _destAC = c._ac._base;
+ int monsterIndex = getMonsterIndex();
+ _attackerLevel = _arr1[monsterIndex] * 2 + 4;
+
+ if (c._condition & (ASLEEP | BLINDED | PARALYZED))
+ _attackerLevel += 5;
+
+ if (_val10) {
+ _attackAttr2._base = _monsterP->_specialAbility & 0x7f;
+ _numberOfTimes = 1;
+
+ } else {
+ _numberOfTimes = _monsterP->_numberOfAttacks;
+ _attackAttr2._base = _monsterP->_maxDamage;
+ }
+
+ if (g_globals->_activeSpells._s.invisbility)
+ _destAC += 3;
+
+ if (g_globals->_activeSpells._s.cursed) {
+ _attackAttr2._current = g_globals->_activeSpells._s.cursed;
+
+ int attackerLevel = attackerLevel + _attackAttr2._current;
+ _attackerLevel = (attackerLevel > 255) ? 192 : attackerLevel;
+ }
+
+ msg._lines.back()._text += ' ';
+ msg._lines.back()._text += getAttackString();
+
+ if (g_globals->_activeSpells._s.power_shield)
+ _damage /= 2;
+
+ if (_val10 && g_globals->_activeSpells._s.shield)
+ _damage = MAX((int)_damage - 8, 0);
+
+ // TODO
+}
+
+Common::String Combat::getAttackString() {
+ Common::String line1;
+ if (_numberOfTimes == 1) {
+ line1 = STRING["dialogs.combat.once"];
+ } else {
+ line1 = Common::String::format("%d %s", _numberOfTimes,
+ STRING["dialogs.combat.times"].c_str());
+ }
+
+ line1 += Common::String::format(" %s ", STRING["dialogs.combat.and"].c_str());
+
+ if (_damage == 0) {
+ line1 += STRING["dialogs.combat.misses"];
+ } else {
+ line1 += STRING["dialogs.combat.hit"];
+ line1 += ' ';
+
+ if (_numberOfTimes > 1) {
+ if (_timesHit == 1) {
+ line1 += STRING["dialogs.combat.once"];
+ } else {
+ line1 += Common::String::format("%d %s", _timesHit,
+ STRING["dialogs.combat.times"].c_str());
+ }
+ }
+
+ line1 += Common::String::format(" %s %d %s",
+ STRING["dialogs.combat.for"].c_str(), _damage,
+ STRING[_damage == 1 ? "dialogs.combat.point" : "dialogs.combat.points"].c_str());
+
+ if (line1.size() < 30) {
+ line1 += ' ';
+ line1 += STRING["dialogs.combat.of_damage"];
+ } else {
+ line1 += '!';
+ }
+ }
+
+ return line1;
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 06fd71226b4..cced8f8936a 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -52,7 +52,8 @@ protected:
bool _allowFight, _allowShoot, _allowCast, _allowAttack;
byte _val6, _val7;
int _val8, _val9, _val10;
- int _val11, _numberOfTimes;
+ int _destAC;
+ int _numberOfTimes;
int _attackerLevel;
int _advanceIndex;
int _handicap1, _handicap2;
@@ -75,7 +76,7 @@ protected:
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL,
- CHAR_ATTACKS
+ CHAR_ATTACKS, MONSTER_ATTACK
};
Mode _mode = SELECT_OPTION;
@@ -243,6 +244,17 @@ protected:
*/
bool monsterTouch(Common::String &line);
+ /**
+ * Handles monster atttack logic
+ */
+ void monsterAttack(InfoMessage &msg);
+ void monsterAttack2(InfoMessage &msg);
+
+ /**
+ * Get attack damage string
+ */
+ Common::String getAttackString();
+
private:
void spellFailed();
void destroyMonster();
diff --git a/engines/mm/mm1/messages.cpp b/engines/mm/mm1/messages.cpp
index 9a16e584d5e..2ab8d9d872c 100644
--- a/engines/mm/mm1/messages.cpp
+++ b/engines/mm/mm1/messages.cpp
@@ -99,6 +99,15 @@ InfoMessage &InfoMessage::operator=(const InfoMessage &src) {
return *this;
}
+size_t Line::size() const {
+ size_t total = 0;
+ for (uint i = 0; i < _text.size(); ++i) {
+ if (_text[i] != '|')
+ ++total;
+ }
+
+ return total;
+}
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index ef2510a39ad..c684771a920 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -101,6 +101,8 @@ struct Line : public Common::Point {
Line(int x1, int y1, const Common::String &text) :
Common::Point(x1, y1), _text(text) {
}
+
+ size_t size() const;
};
typedef Common::Array<Line> LineArray;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index d7588122ee4..373b90b2d5d 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -646,44 +646,7 @@ void Combat::writeCharAttackDamage() {
));
_isShooting = false;
- Common::String line1;
- if (_numberOfTimes == 1) {
- line1 = STRING["dialogs.combat.once"];
- } else {
- line1 = Common::String::format("%d %s", _numberOfTimes,
- STRING["dialogs.combat.times"].c_str());
- }
-
- line1 += Common::String::format(" %s ", STRING["dialogs.combat.and"].c_str());
-
- if (_damage == 0) {
- line1 += STRING["dialogs.combat.misses"];
- } else {
- line1 += STRING["dialogs.combat.hit"];
- line1 += ' ';
-
- if (_numberOfTimes > 1) {
- if (_timesHit == 1) {
- line1 += STRING["dialogs.combat.once"];
- } else {
- line1 += Common::String::format("%d %s", _timesHit,
- STRING["dialogs.combat.times"].c_str());
- }
- }
-
- line1 += Common::String::format(" %s %d %s",
- STRING["dialogs.combat.for"].c_str(), _damage,
- STRING[_damage == 1 ? "dialogs.combat.point" : "dialogs.combat.points"].c_str());
-
- if (line1.size() < 30) {
- line1 += ' ';
- line1 += STRING["dialogs.combat.of_damage"];
- } else {
- line1 += '!';
- }
- }
-
- writeString(0, 1, line1);
+ writeString(0, 1, getAttackString());
}
void Combat::setOption(SelectedOption option) {
Commit: caa5347b2e45cac7102541756a30d69333b49bc3
https://github.com/scummvm/scummvm/commit/caa5347b2e45cac7102541756a30d69333b49bc3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Shifting monster attack string display to view class
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 63255b29160..2dcdc014572 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1386,24 +1386,18 @@ void Combat::disintegration() {
displaySpellResult(msg);
}
-void Combat::monsterAttack(InfoMessage &msg) {
- int styleNum = getRandomNumber(
- (msg._lines.back().size() < 13) ? 15 : 11);
- Common::String attackStyle = STRING[Common::String::format(
- "dialogs.combat.attack_types.%d", styleNum)];
+void Combat::monsterAttackRandom() {
+ size_t monsterNameSize = _monsterList[getMonsterIndex()]._name.size() + 1;
+
+ _monsterAttackStyle = getRandomNumber((monsterNameSize < 13) ? 15 : 11);
_val10 = 0;
- msg._lines.back()._text += attackStyle;
- monsterAttack2(msg);
+ monsterAttackInner();
}
-void Combat::monsterAttack2(InfoMessage &msg) {
+void Combat::monsterAttackInner() {
Character &c = *g_globals->_currCharacter;
- // Add the destination character being attacked
- msg._lines.back()._text += ' ';
- msg._lines.back()._text += c.getDisplayName();
-
_destAC = c._ac._base;
int monsterIndex = getMonsterIndex();
_attackerLevel = _arr1[monsterIndex] * 2 + 4;
@@ -1430,57 +1424,7 @@ void Combat::monsterAttack2(InfoMessage &msg) {
_attackerLevel = (attackerLevel > 255) ? 192 : attackerLevel;
}
- msg._lines.back()._text += ' ';
- msg._lines.back()._text += getAttackString();
-
- if (g_globals->_activeSpells._s.power_shield)
- _damage /= 2;
-
- if (_val10 && g_globals->_activeSpells._s.shield)
- _damage = MAX((int)_damage - 8, 0);
-
- // TODO
-}
-
-Common::String Combat::getAttackString() {
- Common::String line1;
- if (_numberOfTimes == 1) {
- line1 = STRING["dialogs.combat.once"];
- } else {
- line1 = Common::String::format("%d %s", _numberOfTimes,
- STRING["dialogs.combat.times"].c_str());
- }
-
- line1 += Common::String::format(" %s ", STRING["dialogs.combat.and"].c_str());
-
- if (_damage == 0) {
- line1 += STRING["dialogs.combat.misses"];
- } else {
- line1 += STRING["dialogs.combat.hit"];
- line1 += ' ';
-
- if (_numberOfTimes > 1) {
- if (_timesHit == 1) {
- line1 += STRING["dialogs.combat.once"];
- } else {
- line1 += Common::String::format("%d %s", _timesHit,
- STRING["dialogs.combat.times"].c_str());
- }
- }
-
- line1 += Common::String::format(" %s %d %s",
- STRING["dialogs.combat.for"].c_str(), _damage,
- STRING[_damage == 1 ? "dialogs.combat.point" : "dialogs.combat.points"].c_str());
-
- if (line1.size() < 30) {
- line1 += ' ';
- line1 += STRING["dialogs.combat.of_damage"];
- } else {
- line1 += '!';
- }
- }
-
- return line1;
+ setMode(MONSTER_ATTACK);
}
} // namespace Game
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index cced8f8936a..cb87364d5b1 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -86,6 +86,8 @@ protected:
bool _divineInterventionUsed = false;
size_t _spellMonsterCount = 0;
+ int _monsterAttackStyle = -1;
+
/**
* Constructor
*/
@@ -247,13 +249,8 @@ protected:
/**
* Handles monster atttack logic
*/
- void monsterAttack(InfoMessage &msg);
- void monsterAttack2(InfoMessage &msg);
-
- /**
- * Get attack damage string
- */
- Common::String getAttackString();
+ void monsterAttackRandom();
+ void monsterAttackInner();
private:
void spellFailed();
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 9604dc6941c..e5ba3078923 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -133,12 +133,6 @@ private:
*/
void writeDamage();
- /**
- * Subtracts the damage from the character, making
- * them unconscious or die if needed
- */
- void subtractDamage();
-
bool testElementalResistance();
/**
@@ -189,6 +183,12 @@ protected:
void proc9();
+ /**
+ * Subtracts the damage from the character, making
+ * them unconscious or die if needed
+ */
+ void subtractDamage();
+
public:
SpellsMonsters();
virtual ~SpellsMonsters() {}
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 373b90b2d5d..8d94ae5015f 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -104,6 +104,10 @@ void Combat::draw() {
writeMonsterSpell();
delaySeconds(2);
return;
+ case MONSTER_ATTACK:
+ writeMonsterAttack();
+ delaySeconds(4);
+ return;
case CHAR_ATTACKS:
writeMonsters();
writeCharAttackDamage();
@@ -563,6 +567,44 @@ void Combat::writeMonsterSpell() {
}
}
+void Combat::writeMonsterAttack() {
+ Common::String monsterName = _monsterP->_name;
+ Common::String attackStyle = STRING[Common::String::format(
+ "dialogs.combat.attack_types.%d", _monsterAttackStyle)];
+ Character &c = *g_globals->_currCharacter;
+
+ Common::String line = Common::String::format("%s %s %s",
+ monsterName.c_str(),
+ attackStyle.c_str(),
+ getAttackString().c_str()
+ );
+ writeString(0, 20, line);
+
+ // It's not ideal, but we have to do some final minor damage
+ // adjustment here after we've written the basic damage the
+ // character will receive
+ if (g_globals->_activeSpells._s.power_shield)
+ _damage /= 2;
+
+ if (_val10 && g_globals->_activeSpells._s.shield)
+ _damage = MAX((int)_damage - 8, 0);
+
+ if (_damage) {
+ // Attacks wake up sleeping characters
+ if (!(c._condition & BAD_CONDITION))
+ c._condition &= ~ASLEEP;
+
+ // Also check for secondary monster touch action here
+ // This returns a text line to display, and can also
+ // adjust the damage amount. Another reason why we
+ // can't actually apply damage until here
+ if (monsterTouch(line))
+ writeString(0, 21, line);
+
+ subtractDamage();
+ }
+}
+
void Combat::checkMonsterSpellDone() {
for (uint i = 0; i < _monsterSpellLines.size(); ++i) {
if (i > 0 && _monsterSpellLines[i].y ==
@@ -649,6 +691,47 @@ void Combat::writeCharAttackDamage() {
writeString(0, 1, getAttackString());
}
+Common::String Combat::getAttackString() {
+ Common::String line1;
+ if (_numberOfTimes == 1) {
+ line1 = STRING["dialogs.combat.once"];
+ } else {
+ line1 = Common::String::format("%d %s", _numberOfTimes,
+ STRING["dialogs.combat.times"].c_str());
+ }
+
+ line1 += Common::String::format(" %s ", STRING["dialogs.combat.and"].c_str());
+
+ if (_damage == 0) {
+ line1 += STRING["dialogs.combat.misses"];
+ } else {
+ line1 += STRING["dialogs.combat.hit"];
+ line1 += ' ';
+
+ if (_numberOfTimes > 1) {
+ if (_timesHit == 1) {
+ line1 += STRING["dialogs.combat.once"];
+ } else {
+ line1 += Common::String::format("%d %s", _timesHit,
+ STRING["dialogs.combat.times"].c_str());
+ }
+ }
+
+ line1 += Common::String::format(" %s %d %s",
+ STRING["dialogs.combat.for"].c_str(), _damage,
+ STRING[_damage == 1 ? "dialogs.combat.point" : "dialogs.combat.points"].c_str());
+
+ if (line1.size() < 30) {
+ line1 += ' ';
+ line1 += STRING["dialogs.combat.of_damage"];
+ } else {
+ line1 += '!';
+ }
+ }
+
+ return line1;
+}
+
void Combat::setOption(SelectedOption option) {
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
_option = option;
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 6e1ebaa9a48..c18bc481965 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -120,6 +120,11 @@ private:
*/
void writeMonsterSpell();
+ /**
+ * Write out monster's attack
+ */
+ void writeMonsterAttack();
+
/**
* Whether there's messages remaining
*/
@@ -175,6 +180,11 @@ private:
*/
void writeCharAttackDamage();
+ /**
+ * Get attack damage string
+ */
+ Common::String getAttackString();
+
/**
* Writes out a message
*/
Commit: c8f03cf27906b8673626da6110c5b54a7916eb27
https://github.com/scummvm/scummvm/commit/c8f03cf27906b8673626da6110c5b54a7916eb27
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Hooked up subtractDamage for monster attacks
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 2dcdc014572..93c07fe65db 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1420,7 +1420,7 @@ void Combat::monsterAttackInner() {
if (g_globals->_activeSpells._s.cursed) {
_attackAttr2._current = g_globals->_activeSpells._s.cursed;
- int attackerLevel = attackerLevel + _attackAttr2._current;
+ int attackerLevel = _attackerLevel + _attackAttr2._current;
_attackerLevel = (attackerLevel > 255) ? 192 : attackerLevel;
}
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 261c50fc8fc..f451beac37e 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -447,11 +447,7 @@ bool SpellsMonsters::casts() {
}
void SpellsMonsters::addCharName() {
- // Wrap name in special characters so that characters
- // with multiple word names will capitalize each word
- // of the name
- add(Common::String("|%s|",
- g_globals->_currCharacter->_name));
+ add(g_globals->_currCharacter->getDisplayName());
}
void SpellsMonsters::damageRandomChar() {
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index e5ba3078923..fdab130b21c 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -40,7 +40,6 @@ typedef void (SpellsMonsters::*SpellMonstersSpell)();
class SpellsMonsters : public GameLogic {
private:
static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
- LineArray _lines;
void spell01_curse();
void spell02_energyBlast();
@@ -146,6 +145,7 @@ private:
void handlePartyEffects();
protected:
+ LineArray _lines;
byte _arr1[MAX_COMBAT_MONSTERS];
byte _monsterStatus[MAX_COMBAT_MONSTERS];
int _damage = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 8d94ae5015f..90e5b1532e0 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -175,6 +175,9 @@ void Combat::timeout() {
g_events->send("Game", GameMessage("UPDATE"));
return;
}
+ case MONSTER_ATTACK:
+ checkParty();
+ return;
default:
break;
}
@@ -601,7 +604,15 @@ void Combat::writeMonsterAttack() {
if (monsterTouch(line))
writeString(0, 21, line);
+ // TODO: Maybe refactor subtractDamage to not use
+ // the _lines/add methods, which would make it cleaner
+ // to call it from here
+ _lines.clear();
+ _lines.push_back(Line(0, 2, ""));
subtractDamage();
+
+ if (!_lines.back()._text.empty())
+ writeString(0, 22, _lines.back()._text);
}
}
Commit: 277bd710a4255543c57407dc60ba43a576c44277
https://github.com/scummvm/scummvm/commit/277bd710a4255543c57407dc60ba43a576c44277
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Monsters selecting party target
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 14863d5bafa..ae79a3975ad 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -388,6 +388,7 @@
shoot_which: "SHOOT WHICH 'A'-'%d'?"
set_delay: "SET DELAY (0-9):"
delay_currently: "(CURRENTLY= %d)"
+ infiltration: "INFILTRATES THE RANKS!"
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 84a63c7f719..0ca04708d97 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -76,6 +76,10 @@ struct Monster {
byte _field1d;
byte _field1e;
byte _field1f;
+
+ Common::String getDisplayName() const {
+ return Common::String::format("|%s|", _name.c_str());
+ }
};
class Monsters : public TextParser {
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 93c07fe65db..10d711db246 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -49,7 +49,8 @@ void Combat::clear() {
_allowFight = _allowShoot = _allowCast = _allowAttack = false;
_val1 = 0;
_val6 = _val7 = 0;
- _val8 = _val9 = _val10 = 0;
+ _partyIndex = _val9 = 0;
+ _val10 = _destCharCtr = 0;
_destAC = 0;
_numberOfTimes = 0;
_attackerLevel = 0;
@@ -411,7 +412,7 @@ void Combat::nextRound() {
clearArrays();
g_globals->_party.updateAC();
- _val8 = getRandomNumber(_party.size());
+ _partyIndex = getRandomNumber(_party.size());
updateHighestLevel();
setMode(NEXT_ROUND);
@@ -647,17 +648,8 @@ void Combat::removeMonster() {
void Combat::checkParty() {
_val10 = 0;
- bool partyAlive = false;
- for (auto &c : _party) {
- if (!(c->_condition & (DEAD | BAD_CONDITION)))
- partyAlive = true;
- }
-
- if (!partyAlive) {
- g_events->clearViews();
- g_events->replaceView("Dead");
+ if (g_globals->_party.checkPartyDead())
return;
- }
// Update the array for the party
for (uint i = 0; i < _party.size(); ++i) {
@@ -1427,6 +1419,45 @@ void Combat::monsterAttackInner() {
setMode(MONSTER_ATTACK);
}
+void Combat::selectMonsterTarget() {
+ // Iterate through finding a character target for the monster
+ do {
+ uint idx = _partyIndex + 1;
+ if (idx >= g_globals->_party.size())
+ idx = 0;
+
+ // Find a party position that can attack
+ int wrapCount = 0;
+ while (!_canAttack[idx]) {
+ if (++idx >= g_globals->_party.size()) {
+ idx = 0;
+ if (++wrapCount > 1)
+ error("No-one in party could attack. Shouldn't happen");
+ }
+ }
+ _partyIndex = idx;
+ Character &c = g_globals->_party[_partyIndex];
+ g_globals->_currCharacter = &c;
+
+ if (!(c._condition & BAD_CONDITION) && !(c._condition & UNCONSCIOUS)) {
+ // Monster will attack character using a random attack style
+ // message (which doesn't make any real difference)
+ monsterAttackRandom();
+ return;
+ }
+
+ } while (++_destCharCtr < g_globals->_party.size());
+
+ // At this point, fall back on a generic display message
+ // that the monster infiltrates the ranks, which basically
+ // means enabling the whole party to be able to attack directly
+ for (int i = 0; i < 6; ++i)
+ _canAttack[i] = true;
+ _attackerVal = g_globals->_party.size() * 2;
+
+ setMode(INFILTRATION);
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index cb87364d5b1..4b803723bb4 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -51,7 +51,8 @@ protected:
int _monsterIndex, _currentChar;
bool _allowFight, _allowShoot, _allowCast, _allowAttack;
byte _val6, _val7;
- int _val8, _val9, _val10;
+ int _partyIndex, _val9, _val10;
+ int _destCharCtr;
int _destAC;
int _numberOfTimes;
int _attackerLevel;
@@ -76,7 +77,7 @@ protected:
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL,
- CHAR_ATTACKS, MONSTER_ATTACK
+ CHAR_ATTACKS, MONSTER_ATTACK, INFILTRATION
};
Mode _mode = SELECT_OPTION;
@@ -252,6 +253,11 @@ protected:
void monsterAttackRandom();
void monsterAttackInner();
+ /**
+ * Selects monster to attack
+ */
+ void selectMonsterTarget();
+
private:
void spellFailed();
void destroyMonster();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 90e5b1532e0..b444b48d32c 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -108,11 +108,16 @@ void Combat::draw() {
writeMonsterAttack();
delaySeconds(4);
return;
+ case INFILTRATION:
+ writeInfiltration();
+ delaySeconds(3);
+ return;
case CHAR_ATTACKS:
writeMonsters();
writeCharAttackDamage();
delaySeconds(3);
return;
+
default:
break;
}
@@ -157,6 +162,8 @@ void Combat::timeout() {
checkMonsterSpells();
return;
case MONSTER_WANDERS:
+ case INFILTRATION:
+ case MONSTER_ATTACK:
writeParty();
writeMonsters();
checkParty();
@@ -175,9 +182,6 @@ void Combat::timeout() {
g_events->send("Game", GameMessage("UPDATE"));
return;
}
- case MONSTER_ATTACK:
- checkParty();
- return;
default:
break;
}
@@ -616,6 +620,17 @@ void Combat::writeMonsterAttack() {
}
}
+void Combat::writeInfiltration() {
+ Common::String line = Common::String::format("%s %s",
+ _monsterP->getDisplayName().c_str(),
+ STRING["dialogs.combat.infiltration"].c_str());
+
+ resetBottom();
+ writeString(0, 20, line);
+ Sound::sound(SOUND_2);
+ Sound::sound(SOUND_2);
+}
+
void Combat::checkMonsterSpellDone() {
for (uint i = 0; i < _monsterSpellLines.size(); ++i) {
if (i > 0 && _monsterSpellLines[i].y ==
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index c18bc481965..bc9028d440e 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -125,6 +125,11 @@ private:
*/
void writeMonsterAttack();
+ /**
+ * Write message for monster infiltrating the party
+ */
+ void writeInfiltration();
+
/**
* Whether there's messages remaining
*/
Commit: f7864d7dbc431fe922e6425f6f403e5caf890a56
https://github.com/scummvm/scummvm/commit/f7864d7dbc431fe922e6425f6f403e5caf890a56
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Monster shooting logic
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ae79a3975ad..ae1a19059bf 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -416,6 +416,7 @@
12: "SLASHES AT"
13: "STRIKES AT"
14: "THRASHES AT"
+ 99: "SHOOTS AT"
enhdialogs:
character:
stats:
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 0ca04708d97..6fefbb2f7c5 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -54,6 +54,7 @@ enum Fiedl1A {
};
enum Field1E {
+ FIELD1E_F = 0xf,
FIELD1E_10 = 0x10, FIELD1E_20 = 0x20,
FIELD1E_40 = 0x40, FIELD1E_80 = 0x80
};
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 10d711db246..03437540bc0 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -51,6 +51,7 @@ void Combat::clear() {
_val6 = _val7 = 0;
_partyIndex = _val9 = 0;
_val10 = _destCharCtr = 0;
+ _val2 = 0;
_destAC = 0;
_numberOfTimes = 0;
_attackerLevel = 0;
@@ -596,38 +597,72 @@ void Combat::checkMonsterFlees() {
}
}
-void Combat::checkMonsterSpells() {
+bool Combat::checkMonsterSpells() {
if (_monsterList.empty()) {
setMode(DEFEATED_MONSTERS);
- return;
+ return true;
}
if (_monsterStatus[_monsterIndex] & MONFLAG_MINDLESS) {
setMode(MONSTER_WANDERS);
- } else {
- if (!_monsterP->_specialAbility || (_monsterP->_specialAbility & 0x80) ||
- (getRandomNumber(100) >= _monsterP->_field1d) ||
- !(_monsterP->_field1e & 0xf))
- checkMonsterActions();
- else {
- _monsterP->_field1e--;
- if (!_monsterP->_specialAbility || _monsterP->_specialAbility >= 33) {
- checkMonsterActions();
- } else {
- castMonsterSpell(_monsterList[_monsterIndex]._name,
- _monsterP->_specialAbility);
- setMode(MONSTER_SPELL);
- }
- return;
- }
+ return true;
}
+
+ if (!_monsterP->_specialAbility || (_monsterP->_specialAbility & 0x80) ||
+ (getRandomNumber(100) >= _monsterP->_field1d) ||
+ !(_monsterP->_field1e & 0xf))
+ return false;
+
+ _monsterP->_field1e--;
+ if (!_monsterP->_specialAbility || _monsterP->_specialAbility >= 33)
+ return false;
+
+ castMonsterSpell(_monsterList[_monsterIndex]._name,
+ _monsterP->_specialAbility);
+ setMode(MONSTER_SPELL);
+ return true;
}
void Combat::checkMonsterActions() {
+ if (checkMonsterSpells())
+ // Monster wandered or cast spell, so things are taken care of. Exit
+ return;
+ _destCharCtr = 0;
+ if (_val2 < _attackerVal) {
+ selectMonsterTarget();
+ return;
+ }
+ if (!(_monsterP->_specialAbility & 0x80) || !(_monsterP->_field1e & FIELD1E_F)) {
+ setMode(WAITS_FOR_OPENING);
+ return;
+ }
- // TODO
+ _monsterP->_field1e--;
+
+ // Pick a random character to shoot at
+ int charNum = getRandomNumber(g_globals->_party.size()) - 1;
+ Character &c = g_globals->_party[charNum];
+ g_globals->_currCharacter = &c;
+
+ if (!(c._condition & (BAD_CONDITION | UNCONSCIOUS))) {
+ monsterAttackShooting();
+ return;
+ }
+
+ // Chosen character was incapitated, so scan through party
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ c = g_globals->_party[i];
+
+ if (!(c._condition & (BAD_CONDITION | UNCONSCIOUS))) {
+ g_globals->_currCharacter = &c;
+ monsterAttackShooting();
+ return;
+ }
+ }
+
+ checkParty();
}
void Combat::removeMonster() {
@@ -1387,6 +1422,14 @@ void Combat::monsterAttackRandom() {
monsterAttackInner();
}
+void Combat::monsterAttackShooting() {
+ ++_val10;
+ _monsterAttackStyle = 99; // shooting
+
+ monsterAttackInner();
+}
+
+
void Combat::monsterAttackInner() {
Character &c = *g_globals->_currCharacter;
@@ -1446,7 +1489,7 @@ void Combat::selectMonsterTarget() {
return;
}
- } while (++_destCharCtr < g_globals->_party.size());
+ } while (++_destCharCtr < (int)g_globals->_party.size());
// At this point, fall back on a generic display message
// that the monster infiltrates the ranks, which basically
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 4b803723bb4..5a5fedc0f3a 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -52,6 +52,7 @@ protected:
bool _allowFight, _allowShoot, _allowCast, _allowAttack;
byte _val6, _val7;
int _partyIndex, _val9, _val10;
+ int _val2;
int _destCharCtr;
int _destAC;
int _numberOfTimes;
@@ -77,7 +78,8 @@ protected:
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL,
- CHAR_ATTACKS, MONSTER_ATTACK, INFILTRATION
+ CHAR_ATTACKS, MONSTER_ATTACK, INFILTRATION,
+ WAITS_FOR_OPENING
};
Mode _mode = SELECT_OPTION;
@@ -205,7 +207,7 @@ protected:
/**
* Check if monster is mindless and wandering
*/
- void checkMonsterSpells();
+ bool checkMonsterSpells();
/**
* Check other monster actions
@@ -253,6 +255,11 @@ protected:
void monsterAttackRandom();
void monsterAttackInner();
+ /**
+ * Handles monster shooting a character
+ */
+ void monsterAttackShooting();
+
/**
* Selects monster to attack
*/
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index b444b48d32c..f399964f6b8 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -112,6 +112,10 @@ void Combat::draw() {
writeInfiltration();
delaySeconds(3);
return;
+ case WAITS_FOR_OPENING:
+ writeWaitsForOpening();
+ delaySeconds(2);
+ return;
case CHAR_ATTACKS:
writeMonsters();
writeCharAttackDamage();
@@ -171,6 +175,9 @@ void Combat::timeout() {
case MONSTER_SPELL:
checkMonsterSpellDone();
return;
+ case WAITS_FOR_OPENING:
+ loop1();
+ return;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_activeSpells;
spells._s.bless = 0;
@@ -631,6 +638,16 @@ void Combat::writeInfiltration() {
Sound::sound(SOUND_2);
}
+void Combat::writeWaitsForOpening() {
+ Common::String line = Common::String::format("%s %s",
+ _monsterP->getDisplayName().c_str(),
+ STRING["dialogs.combat.infiltration"].c_str()
+ );
+
+ resetBottom();
+ writeString(0, 20, line);
+}
+
void Combat::checkMonsterSpellDone() {
for (uint i = 0; i < _monsterSpellLines.size(); ++i) {
if (i > 0 && _monsterSpellLines[i].y ==
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index bc9028d440e..8ce9ce8b305 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -130,6 +130,11 @@ private:
*/
void writeInfiltration();
+ /**
+ * Write message for monster waits for an opening
+ */
+ void writeWaitsForOpening();
+
/**
* Whether there's messages remaining
*/
Commit: 6d89e52d1756a9a921dd16522b81ece629657869
https://github.com/scummvm/scummvm/commit/6d89e52d1756a9a921dd16522b81ece629657869
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Fix combat party incapacitated check
Changed paths:
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index d32bdff582a..452fa7cc771 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -103,8 +103,8 @@ bool Party::hasItem(byte itemId) const {
}
bool Party::isPartyDead() const {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
+ for (uint i = 0; i < size(); ++i) {
+ const Character &c = (*this)[i];
if (!(c._condition & (ASLEEP | PARALYZED | UNCONSCIOUS | BAD_CONDITION)))
return false;
}
@@ -123,6 +123,21 @@ bool Party::checkPartyDead() const {
}
}
+bool Party::checkPartyIncapacitated() const {
+ bool isActive = false;
+ for (uint i = 0; i < size() && !isActive; ++i) {
+ const Character &c = (*this)[i];
+ isActive = !(c._condition & (BAD_CONDITION | UNCONSCIOUS));
+ }
+
+ if (isActive) {
+ g_events->replaceView("Dead", true);
+ return true;
+ } else {
+ return false;
+ }
+}
+
void Party::synchronize(Common::Serializer &s) {
int partySize = size();
s.syncAsByte(partySize);
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index ee5c9bdcc83..767462f17cf 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -82,6 +82,12 @@ struct Party : public Common::Array<Character> {
*/
bool checkPartyDead() const;
+ /**
+ * Checks whether the party is incapitated, and if so,
+ * switches to the death screen
+ */
+ bool checkPartyIncapacitated() const;
+
/**
* Synchronizes the party to/from savegames
*/
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 03437540bc0..6e96d4a2372 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -683,12 +683,12 @@ void Combat::removeMonster() {
void Combat::checkParty() {
_val10 = 0;
- if (g_globals->_party.checkPartyDead())
+ if (g_globals->_party.checkPartyIncapacitated())
return;
// Update the array for the party
for (uint i = 0; i < _party.size(); ++i) {
- Character &c = *_party[i];
+ const Character &c = *_party[i];
if ((c._condition & BAD_CONDITION) || !c._hpBase)
_arr3[i] = 1;
}
Commit: ee05e6cb44b2dc9152fcf50b145ed63d9efff21f
https://github.com/scummvm/scummvm/commit/ee05e6cb44b2dc9152fcf50b145ed63d9efff21f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Move several standalone arrays into Monster
This also fixes some methods in MonsterSpells, which
were accidentally referring to the wrong arrays
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/data/party.cpp
engines/mm/mm1/data/party.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index cdd670e971b..c8965f46085 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -42,8 +42,8 @@ bool Monsters::load() {
mon._count = getNextValue(line);
mon._field10 = getNextValue(line);
- mon._field11 = getNextValue(line);
- mon._field12 = getNextValue(line);
+ mon._defaultHP = getNextValue(line);
+ mon._defaultAC = getNextValue(line);
mon._maxDamage = getNextValue(line);
mon._numberOfAttacks = getNextValue(line);
mon._speed = getNextValue(line);
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 6fefbb2f7c5..a4565e26aa6 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -63,8 +63,8 @@ struct Monster {
Common::String _name; // char _name[15];
byte _count;
byte _field10;
- byte _field11;
- byte _field12;
+ byte _defaultHP;
+ byte _defaultAC;
byte _maxDamage;
byte _numberOfAttacks;
byte _speed;
@@ -78,6 +78,12 @@ struct Monster {
byte _field1e;
byte _field1f;
+ // Runtime combat fields
+ byte _combat1 = 0;
+ byte _status = 0;
+ byte _hp = 0;
+ byte _ac = 0;
+
Common::String getDisplayName() const {
return Common::String::format("|%s|", _name.c_str());
}
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index 452fa7cc771..a74791d19cd 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -148,5 +148,19 @@ void Party::synchronize(Common::Serializer &s) {
(*this)[i].synchronize(s);
}
+void Party::rearrange(const Common::Array<Character *> &party) {
+ assert(party.size() == size());
+
+ for (uint i = 0; i < size(); ++i) {
+ for (uint j = i; j < size(); ++j) {
+ if (party[i] == &(*this)[j]) {
+ if (j != i)
+ insert_at(i, remove_at(j));
+ break;
+ }
+ }
+ }
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h
index 767462f17cf..4f56a4f91c6 100644
--- a/engines/mm/mm1/data/party.h
+++ b/engines/mm/mm1/data/party.h
@@ -88,6 +88,11 @@ struct Party : public Common::Array<Character> {
*/
bool checkPartyIncapacitated() const;
+ /**
+ * Reorder the party based on a passed array of character pointers
+ */
+ void rearrange(const Common::Array<Character *> &party);
+
/**
* Synchronizes the party to/from savegames
*/
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 6e96d4a2372..14e94f9d235 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -28,7 +28,7 @@ namespace MM {
namespace MM1 {
namespace Game {
-Combat::Combat() : _monsterList(g_globals->_encounters._monsterList) {
+Combat::Combat() : MonsterTouch() {
g_globals->_combat = this;
clear();
}
@@ -38,11 +38,8 @@ Combat::~Combat() {
}
void Combat::clear() {
- Common::fill(&_monsterHP[0], &_monsterHP[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_monsterAC[0], &_monsterAC[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
Common::fill(&_arr4[0], &_arr4[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
Common::fill(&_treasureFlags[0], &_treasureFlags[MAX_PARTY_SIZE], false);
@@ -90,9 +87,9 @@ void Combat::loadArrays() {
Monster &mon = enc._monsterList[i];
int val = getRandomNumber(8);
- mon._field11 += val;
- _monsterHP[i] = mon._field11;
- _monsterAC[i] = mon._field12;
+ mon._defaultHP += val;
+ mon._hp = mon._defaultHP;
+ mon._ac = mon._defaultAC;
monsterIndexOf();
}
@@ -217,7 +214,7 @@ void Combat::setupHandicap() {
bool Combat::canMonsterCast() const {
return !(g_maps->_currentState & Maps::SFLAG_DISABLE_MONSTER_SPELLS) &&
- !(_monsterStatus[_monsterIndex] & (MONFLAG_BLIND | MONFLAG_SILENCED));
+ !(_monsterList[_monsterIndex]._status & (MONFLAG_BLIND | MONFLAG_SILENCED));
}
void Combat::dispelParty() {
@@ -240,7 +237,7 @@ void Combat::dispelParty() {
for (uint i = 0; i < _monsterList.size(); ++i) {
monsterSetPtr(i);
- _monsterStatus[i] = 0;
+ _monsterList[i]._status = 0;
}
_monsterP = tmpM;
@@ -282,7 +279,7 @@ void Combat::defeatedMonsters() {
monsterIndexOf();
_totalExperience += _monsterP->_experience;
- proc1();
+ setTreasure();
}
// Count number of active characters
@@ -301,7 +298,7 @@ void Combat::defeatedMonsters() {
// Update the party's characters
g_globals->_party.combatDone();
- // TODO
+ combatDone();
}
void Combat::loop1() {
@@ -313,7 +310,7 @@ void Combat::loop1() {
&& !_arr4[i]) {
_arr4[i] = true;
- if (_monsterStatus[i] & (MONFLAG_ASLEEP | MONFLAG_HELD |
+ if (_monsterList[i]._status & (MONFLAG_ASLEEP | MONFLAG_HELD |
MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
checkMonsterFlees();
return;
@@ -331,7 +328,7 @@ void Combat::loop1() {
}
}
-void Combat::proc1() {
+void Combat::setTreasure() {
_val7 = _monsterP->_field18;
_val6 = MAX(_val6, _val7);
@@ -465,7 +462,7 @@ bool Combat::moveMonsters() {
for (uint i = 0; i < _monsterList.size(); ++i) {
_advanceIndex = i;
- if (!(_monsterStatus[i] & ~MONFLAG_SILENCED) &&
+ if (!(_monsterList[i]._status & ~MONFLAG_SILENCED) &&
_monsterList[i]._field1e & FIELD1E_80) {
monsterAdvances();
hasAdvance = true;
@@ -488,52 +485,52 @@ bool Combat::monsterChanges() {
monsterSetPtr(i);
if ((_monsterP->_field1e & FIELD1E_40) &&
- (_monsterP->_field11 != _monsterHP[i])) {
+ (_monsterP->_defaultHP != _monsterList[i]._hp)) {
_monstersRegenerate = true;
- int newVal = _monsterHP[i] + 5;
- _monsterHP[i] = (byte)newVal;
+ int newVal = _monsterList[i]._hp + 5;
+ _monsterList[i]._hp = (byte)newVal;
- if (newVal >= 256 || newVal >= _monsterP->_field11) {
- _monsterHP[i] = _monsterP->_field11;
+ if (newVal >= 256 || newVal >= _monsterP->_defaultHP) {
+ _monsterList[i]._hp = _monsterP->_defaultHP;
}
}
- if (_monsterStatus[i]) {
+ if (_monsterList[i]._status) {
proc2();
if (_val9) {
_monstersResistSpells = true;
- byte v = _monsterStatus[i];
+ byte v = _monsterList[i]._status;
v &= 0x7f;
- if (v != _monsterStatus[i]) {
- _monsterStatus[i] = v;
+ if (v != _monsterList[i]._status) {
+ _monsterList[i]._status = v;
} else {
v &= 0x3f;
- if (v != _monsterStatus[i]) {
- _monsterStatus[i] = v;
+ if (v != _monsterList[i]._status) {
+ _monsterList[i]._status = v;
} else {
v &= 0x1f;
- if (v != _monsterStatus[i]) {
- _monsterStatus[i] = v;
+ if (v != _monsterList[i]._status) {
+ _monsterList[i]._status = v;
} else {
v &= 0xf;
- if (v != _monsterStatus[i]) {
- _monsterStatus[i] = v;
+ if (v != _monsterList[i]._status) {
+ _monsterList[i]._status = v;
} else {
v &= 7;
- if (v != _monsterStatus[i]) {
- _monsterStatus[i] = v;
+ if (v != _monsterList[i]._status) {
+ _monsterList[i]._status = v;
} else {
v &= 3;
- if (v != _monsterStatus[i]) {
- _monsterStatus[i] = v;
+ if (v != _monsterList[i]._status) {
+ _monsterList[i]._status = v;
} else {
v &= 1;
- if (v != _monsterStatus[i])
- _monsterStatus[i] = v;
+ if (v != _monsterList[i]._status)
+ _monsterList[i]._status = v;
else
- _monsterStatus[i] = 0;
+ _monsterList[i]._status = 0;
}
}
}
@@ -588,8 +585,8 @@ void Combat::checkMonsterFlees() {
if (getRandomNumber(100) >= threshold) {
_monsterP->_experience = 0;
_monsterP->_field18 = 0;
- _monsterHP[_monsterIndex] = 0;
- _monsterStatus[_monsterIndex] = MONFLAG_DEAD;
+ _monsterList[_monsterIndex]._hp = 0;
+ _monsterList[_monsterIndex]._status = MONFLAG_DEAD;
removeMonster();
setMode(MONSTER_FLEES);
} else {
@@ -603,7 +600,7 @@ bool Combat::checkMonsterSpells() {
return true;
}
- if (_monsterStatus[_monsterIndex] & MONFLAG_MINDLESS) {
+ if (_monsterList[_monsterIndex]._status & MONFLAG_MINDLESS) {
setMode(MONSTER_WANDERS);
return true;
}
@@ -671,7 +668,7 @@ void Combat::removeMonster() {
changed = false;
for (uint i = 0; i < _monsterList.size(); ++i) {
_monsterP = &_monsterList[i];
- if (_monsterStatus[i] == MONFLAG_DEAD) {
+ if (_monsterList[i]._status == MONFLAG_DEAD) {
_monsterList.remove_at(i);
changed = true;
break;
@@ -806,7 +803,7 @@ void Combat::attackMonster(int monsterNum) {
_attackAttr2._current += (c._level + 1) / 2;
if (_attackAttr1._current || !(_monsterP->_field1a & FIELD1A_80)) {
- if (_monsterStatus[_monsterIndex] & (MONFLAG_ASLEEP |
+ if (_monsterList[_monsterIndex]._status & (MONFLAG_ASLEEP |
MONFLAG_HELD | MONFLAG_WEBBED | MONFLAG_PARALYZED))
++_attackerLevel;
@@ -847,13 +844,13 @@ void Combat::addAttackDamage() {
}
void Combat::updateMonsterStatus() {
- int val = _monsterHP[_monsterIndex] - _damage;
+ int val = _monsterList[_monsterIndex]._hp - _damage;
if (val <= 0) {
- _monsterHP[_monsterIndex] = 0;
- _monsterStatus[_monsterIndex] = MONFLAG_DEAD;
+ _monsterList[_monsterIndex]._hp = 0;
+ _monsterList[_monsterIndex]._status = MONFLAG_DEAD;
} else {
- _monsterHP[_monsterIndex] = val;
- _monsterStatus[_monsterIndex] &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
+ _monsterList[_monsterIndex]._hp = val;
+ _monsterList[_monsterIndex]._status &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
}
}
@@ -908,7 +905,7 @@ void Combat::iterateMonsters1Inner() {
effect = STRING["monster_spells.not_affected"];
} else {
- _monsterStatus[getMonsterIndex()] |=
+ _monsterList[getMonsterIndex()]._status |=
g_globals->_spellsState._newCondition;
byte bits = g_globals->_spellsState._newCondition;
@@ -1006,7 +1003,7 @@ void Combat::iterateMonsters2Inner() {
msg._lines.push_back(Line(0, 1, line2));
- if (_damage >= _monsterHP[getMonsterIndex()]) {
+ if (_damage >= _monsterList[getMonsterIndex()]._hp) {
msg._lines.push_back(Line(0, 2, STRING["monster_spells.and_goes_down"]));
}
}
@@ -1077,7 +1074,7 @@ void Combat::turnUndead() {
if ((monster->_resistUndead & IS_UNDEAD) &&
(getRandomNumber(20) + g_globals->_currCharacter->_level) >=
- (_monsterHP[i] * 2 + 10)) {
+ (_monsterList[i]._hp * 2 + 10)) {
destroyMonster();
++_monstersDestroyedCtr;
}
@@ -1093,7 +1090,7 @@ void Combat::turnUndead() {
}
void Combat::destroyMonster() {
- _monsterStatus[getMonsterIndex()] = 0xff;
+ _monsterList[getMonsterIndex()]._status = 0xff;
Sound::sound2(SOUND_9);
}
@@ -1214,10 +1211,10 @@ void Combat::identifyMonster() {
while (line.size() < COL2)
line += ' ';
line += STRING["spells.info.hp"];
- line += Common::String::format("%d", _monsterHP[_destMonsterNum]);
+ line += Common::String::format("%d", _monsterList[_destMonsterNum]._hp);
line += " ";
line += STRING["spells.info.ac"];
- line += Common::String::format("%d", _monsterAC[_destMonsterNum]);
+ line += Common::String::format("%d", _monsterList[_destMonsterNum]._ac);
msg._lines.push_back(Line(0, 0, line));
line = STRING["spells.info.speed"];
@@ -1306,7 +1303,7 @@ void Combat::weaken() {
for (uint i = 0; i < _monsterList.size(); ++i) {
monsterSetPtr(i);
- _monsterAC[i] = MAX((int)_monsterAC[i] - 1, 1);
+ _monsterList[i]._ac = MAX((int)_monsterList[i]._ac - 1, 1);
}
resetDestMonster();
@@ -1435,7 +1432,7 @@ void Combat::monsterAttackInner() {
_destAC = c._ac._base;
int monsterIndex = getMonsterIndex();
- _attackerLevel = _arr1[monsterIndex] * 2 + 4;
+ _attackerLevel = _monsterList[monsterIndex]._combat1 * 2 + 4;
if (c._condition & (ASLEEP | BLINDED | PARALYZED))
_attackerLevel += 5;
@@ -1501,6 +1498,17 @@ void Combat::selectMonsterTarget() {
setMode(INFILTRATION);
}
+void Combat::combatDone() {
+ // Reset several active spells
+ g_globals->_activeSpells._s.bless = 0;
+ g_globals->_activeSpells._s.invisbility = 0;
+ g_globals->_activeSpells._s.shield = 0;
+ g_globals->_activeSpells._s.power_shield = 0;
+
+ // Rearrange the party to match the combat order
+ g_globals->_party.rearrange(_party);
+}
+
} // namespace Game
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 5a5fedc0f3a..0f2634f980b 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -35,13 +35,10 @@ namespace Game {
class Combat : public MonsterTouch {
protected:
- Common::Array<Monster> &_monsterList;
Common::Array<Line> _message;
int _monstersCount = 0;
Common::Array<Character *> _party;
Monster *_monsterP;
- byte _monsterHP[MAX_COMBAT_MONSTERS];
- byte _monsterAC[MAX_COMBAT_MONSTERS];
int _arr3[MAX_PARTY_SIZE / 2];
byte _arr4[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
@@ -217,7 +214,7 @@ protected:
void defeatedMonsters();
void selectParty();
void loop1();
- void proc1();
+ void setTreasure();
void clearArrays();
bool moveMonsters();
void monsterAdvances();
@@ -265,6 +262,11 @@ protected:
*/
void selectMonsterTarget();
+ /**
+ * Does final cleanup when combat is done
+ */
+ void combatDone();
+
private:
void spellFailed();
void destroyMonster();
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index eea600275b7..eb02f427eb6 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -40,6 +40,9 @@ void Encounter::execute() {
_bribeFleeCtr = _bribeAlignmentCtr = 0;
_alignmentsChanged = 0;
+ byte combat1[MAX_COMBAT_MONSTERS];
+ Common::fill(&combat1[0], &combat1[MAX_COMBAT_MONSTERS], 0);
+
if (!_flag) {
_monsterList.clear();
_levelIndex = 0;
@@ -80,7 +83,7 @@ void Encounter::execute() {
}
assert(_monsterCount < MAX_COMBAT_MONSTERS);
- _arr1[_monsterCount] = comp;
+ combat1[_monsterCount] = comp;
_monsterNum16 = comp;
_levelIndex += comp;
@@ -97,8 +100,8 @@ void Encounter::execute() {
for (int i = 0; i < maxVal; ++i) {
assert(_monsterCount > 0);
- _arr1[_monsterCount] = _arr1[_monsterCount - 1];
- _levelIndex += _arr1[_monsterCount];
+ combat1[_monsterCount] = combat1[_monsterCount - 1];
+ _levelIndex += combat1[_monsterCount];
_monsIndexes[_monsterCount] = _monsIndexes[_monsterCount - 1];
if (++_monsterCount >= MAX_COMBAT_MONSTERS)
@@ -116,16 +119,18 @@ exit_loop:
_monsterList.clear();
for (int i = 0; i < _monsterCount; ++i) {
- maxVal = (_arr1[i] - 1) * 16 + _monsIndexes[i];
- if (_arr1[i] < 1 || _arr1[i] > 12 || maxVal >= 196) {
- _arr1[i] = 10;
+ maxVal = (combat1[i] - 1) * 16 + _monsIndexes[i];
+ if (combat1[i] < 1 || combat1[i] > 12 || maxVal >= 196) {
+ combat1[i] = 10;
_monsIndexes[i] = getRandomNumber(MAX_COMBAT_MONSTERS);
}
// Add monster details to list
- _monsterNum16 = _arr1[i];
- const Monster &mons = g_globals->_monsters[_monsIndexes[i]];
- _monsterList.push_back(mons);
+ _monsterNum16 = combat1[i];
+ const Monster &srcMons = g_globals->_monsters[_monsIndexes[i]];
+ _monsterList.push_back(srcMons);
+ Monster &mons = _monsterList.back();
+ mons._combat1 = combat1[i];
if (_monsterNum16 > _val9) {
_val9 = _monsterNum16;
@@ -175,7 +180,7 @@ void Encounter::clearMonsters() {
void Encounter::addMonster(byte id, byte arr1) {
const Monster &mons = g_globals->_monsters[id];
_monsterList.push_back(mons);
- _arr1[_monsterList.size() - 1] = arr1;
+ _monsterList.back()._combat1 = arr1;
}
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 187d86d8d13..12ee8727a26 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -57,7 +57,6 @@ public:
int _highestLevel = 0;
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
- byte _arr1[MAX_COMBAT_MONSTERS];
bool _flag = false;
int _levelIndex = 0;
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index f451beac37e..ca92c90f20d 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -63,9 +63,7 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
&SpellsMonsters::spell32_swarm
};
-SpellsMonsters::SpellsMonsters() {
- Common::fill(&_arr1[0], &_arr1[MAX_COMBAT_MONSTERS], 0);
- Common::fill(&_monsterStatus[0], &_monsterStatus[MAX_COMBAT_MONSTERS], 0);
+SpellsMonsters::SpellsMonsters() : _monsterList(g_globals->_encounters._monsterList) {
}
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
@@ -105,7 +103,7 @@ void SpellsMonsters::spell03_fire() {
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
- int count = g_globals->_encounters._arr1[getMonsterIndex()];
+ int count = _monsterList[getMonsterIndex()]._combat1;
g_globals->_spellsState._newCondition += count * 6;
damageRandomChar();
@@ -159,7 +157,7 @@ void SpellsMonsters::spell08_paralyze() {
g_globals->_spellsState._resistanceType = RESISTANCE_FEAR;
g_globals->_spellsState._newCondition = PARALYZED;
- if (g_globals->_encounters._arr1[getMonsterIndex()] >= 5) {
+ if (_monsterList[getMonsterIndex()]._combat1 >= 5) {
handlePartyEffects();
} else {
chooseCharacter();
@@ -201,9 +199,10 @@ void SpellsMonsters::spell12_explode() {
add(STRING["monster_spellsState.explode"]);
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
- g_globals->_spellsState._newCondition = getRandomNumber(_arr1[getMonsterIndex()]);
- _arr1[getMonsterIndex()] = 0;
- _monsterStatus[getMonsterIndex()] = MONFLAG_DEAD;
+ g_globals->_spellsState._newCondition = getRandomNumber(
+ _monsterList[getMonsterIndex()]._combat1);
+ _monsterList[getMonsterIndex()]._combat1 = 0;
+ _monsterList[getMonsterIndex()]._status = MONFLAG_DEAD;
removeMonster();
add(':');
@@ -219,7 +218,7 @@ void SpellsMonsters::spell13_fireball() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 6 *
- g_globals->_encounters._arr1[getMonsterIndex()];
+ _monsterList[getMonsterIndex()]._combat1;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition) + 4;
add(':');
@@ -236,7 +235,7 @@ void SpellsMonsters::spell14_fireBreath() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 8 *
- g_globals->_encounters._arr1[getMonsterIndex()];
+ _monsterList[getMonsterIndex()]._combat1;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition);
add(':');
@@ -351,7 +350,7 @@ void SpellsMonsters::spell25_poison() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.poison"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
- g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -363,7 +362,7 @@ void SpellsMonsters::spell26_lightning() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.lightning"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
- g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -375,7 +374,7 @@ void SpellsMonsters::spell27_frost() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.frost"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_COLD;
- g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -387,7 +386,7 @@ void SpellsMonsters::spell28_spikes() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.spikes"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
- g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -399,7 +398,7 @@ void SpellsMonsters::spell29_acid() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.acid"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ACID;
- g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -411,7 +410,7 @@ void SpellsMonsters::spell30_fire() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.fire"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
- g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -420,7 +419,7 @@ void SpellsMonsters::spell30_fire() {
void SpellsMonsters::spell31_energy() {
add(STRING["monster_spellsState.energy"]);
- g_globals->_spellsState._newCondition = _arr1[getMonsterIndex()];
+ g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index fdab130b21c..46d3e91a550 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -24,6 +24,7 @@
#include "mm/mm1/game/game_logic.h"
#include "mm/mm1/data/character.h"
+#include "mm/mm1/data/monsters.h"
#include "mm/mm1/messages.h"
#include "common/str.h"
@@ -145,9 +146,8 @@ private:
void handlePartyEffects();
protected:
+ Common::Array<Monster> &_monsterList;
LineArray _lines;
- byte _arr1[MAX_COMBAT_MONSTERS];
- byte _monsterStatus[MAX_COMBAT_MONSTERS];
int _damage = 0;
virtual bool canMonsterCast() const = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index f399964f6b8..52715c6d4aa 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -121,7 +121,6 @@ void Combat::draw() {
writeCharAttackDamage();
delaySeconds(3);
return;
-
default:
break;
}
@@ -142,7 +141,7 @@ void Combat::draw() {
case DEFEATED_MONSTERS:
writeDefeat();
Sound::sound2(SOUND_3);
- delaySeconds(3);
+ delaySeconds(5);
break;
default:
@@ -475,7 +474,7 @@ void Combat::writeMonsters() {
void Combat::writeMonsterStatus(int monsterNum) {
monsterSetPtr(monsterNum);
- byte statusBits = _monsterStatus[monsterNum];
+ byte statusBits = _monsterList[monsterNum]._status;
if (statusBits) {
writeDots();
@@ -491,7 +490,7 @@ void Combat::writeMonsterStatus(int monsterNum) {
writeString(STRING[Common::String::format("dialogs.combat.status.%d",
status)]);
- } else if (_monsterHP[monsterNum] != _monsterP->_field11) {
+ } else if (_monsterList[monsterNum]._hp != _monsterP->_defaultHP) {
writeDots();
writeString(STRING["dialogs.combat.status.wounded"]);
} else {
@@ -528,7 +527,7 @@ void Combat::writeDefeat() {
writeString(10, 0, "+----------------------------+");
writeString(10, 2, STRING["dialogs.combat.defeating1"]);
- writeString(10, 4, STRING["dialogs.combat.defeating1"]);
+ writeString(10, 4, STRING["dialogs.combat.defeating2"]);
writeNumber(14, 6, _totalExperience);
_textPos.x++;
writeString(STRING["dialogs.combat.xp"]);
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 8ce9ce8b305..673c2691d61 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -98,6 +98,9 @@ private:
*/
void clearPartyArea();
+ /**
+ * Writes the result of defeating all the monsters
+ */
void writeDefeat();
/**
Commit: d970e70cc5938fe38356d56e99008689c46243bd
https://github.com/scummvm/scummvm/commit/d970e70cc5938fe38356d56e99008689c46243bd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Move _arr4 into Monster as _checked
Changed paths:
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index a4565e26aa6..75f0cabd668 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -80,6 +80,7 @@ struct Monster {
// Runtime combat fields
byte _combat1 = 0;
+ bool _checked = false;
byte _status = 0;
byte _hp = 0;
byte _ac = 0;
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 14e94f9d235..b6758ae597f 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -38,8 +38,9 @@ Combat::~Combat() {
}
void Combat::clear() {
+ _monsterList.clear();
+
Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
- Common::fill(&_arr4[0], &_arr4[MAX_COMBAT_MONSTERS], 0);
Common::fill(&_canAttack[0], &_canAttack[6], false);
Common::fill(&_treasureFlags[0], &_treasureFlags[MAX_PARTY_SIZE], false);
@@ -307,8 +308,8 @@ void Combat::loop1() {
monsterIndexOf();
if (_monsterP->_speed && _monsterP->_speed >= _handicap3
- && !_arr4[i]) {
- _arr4[i] = true;
+ && !_monsterList[i]._checked) {
+ _monsterList[i]._checked = true;
if (_monsterList[i]._status & (MONFLAG_ASLEEP | MONFLAG_HELD |
MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
@@ -436,7 +437,9 @@ void Combat::nextRound3() {
void Combat::clearArrays() {
Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE], 0);
- Common::fill(&_arr4[0], &_arr4[MAX_COMBAT_MONSTERS], 0);
+
+ for (uint i = 0; i < _monsterList.size(); ++i)
+ _monsterList[i]._checked = 0;
}
void Combat::updateHighestLevel() {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 0f2634f980b..9053b39b358 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -40,7 +40,6 @@ protected:
Common::Array<Character *> _party;
Monster *_monsterP;
int _arr3[MAX_PARTY_SIZE / 2];
- byte _arr4[MAX_COMBAT_MONSTERS];
bool _canAttack[MAX_PARTY_SIZE];
bool _treasureFlags[MAX_PARTY_SIZE];
int _val1;
Commit: b8e432b3948388c98cbf56f5e4514808bd4bff00
https://github.com/scummvm/scummvm/commit/b8e432b3948388c98cbf56f5e4514808bd4bff00
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:39+01:00
Commit Message:
MM: MM1: Moved combat character flags to Character
Changed paths:
engines/mm/mm1/data/character.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index f2b8bfed448..d057b342a7d 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -448,6 +448,9 @@ struct Character : public PrimaryAttributes {
// Non persistent fields
byte _numDrinks = 0;
+ // Combat fields
+ byte _combat3 = 0;
+ bool _canAttack = false;
Character();
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b6758ae597f..2c1e56b3475 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -40,8 +40,12 @@ Combat::~Combat() {
void Combat::clear() {
_monsterList.clear();
- Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE / 2], 0);
- Common::fill(&_canAttack[0], &_canAttack[6], false);
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._combat3 = 0;
+ c._canAttack = false;
+ }
+
Common::fill(&_treasureFlags[0], &_treasureFlags[MAX_PARTY_SIZE], false);
_allowFight = _allowShoot = _allowCast = _allowAttack = false;
@@ -115,15 +119,17 @@ void Combat::monsterSetPtr(int monsterNum) {
void Combat::setupCanAttacks() {
const Encounter &enc = g_globals->_encounters;
const Maps::Map &map = *g_maps->_currentMap;
- Common::fill(&_canAttack[0], &_canAttack[MAX_PARTY_SIZE], false);
+
+ for (uint i = 0; i < _party.size(); ++i)
+ _party[i]->_canAttack = false;
if ((int8)map[Maps::MAP_ID] < 0) {
if (enc._encounterType != FORCE_SURPRISED) {
for (uint i = 0; i < _party.size(); ++i) {
if (i < (MAX_PARTY_SIZE - 1)) {
- _canAttack[i] = true;
+ _party[i]->_canAttack = true;
} else {
- _canAttack[MAX_PARTY_SIZE - 1] =
+ _party[MAX_PARTY_SIZE - 1]->_canAttack =
getRandomNumber(100) <= 10;
}
}
@@ -133,20 +139,20 @@ void Combat::setupCanAttacks() {
}
} else {
if (enc._encounterType != FORCE_SURPRISED) {
- _canAttack[0] = true;
+ _party[0]->_canAttack = true;
if (_party.size() > 1)
- _canAttack[1] = true;
+ _party[1]->_canAttack = true;
if (_party.size() > 2)
checkLeftWall();
if (_party.size() > 3)
checkRightWall();
if (_party.size() > 4) {
- if (_canAttack[2] && getRandomNumber(100) <= 5)
- _canAttack[4] = true;
+ if (_party[2]->_canAttack && getRandomNumber(100) <= 5)
+ _party[4]->_canAttack = true;
}
if (_party.size() > 5) {
- if (_canAttack[3] && getRandomNumber(100) <= 5)
- _canAttack[5] = true;
+ if (_party[3]->_canAttack && getRandomNumber(100) <= 5)
+ _party[5]->_canAttack = true;
}
setupAttackerVal();
@@ -157,14 +163,16 @@ void Combat::setupCanAttacks() {
// Entire party is allowed to attack, I guess
// because the monsters are surrounding the party,
// placing them within reach
- Common::fill(&_canAttack[0], &_canAttack[_party.size()], true);
+ for (uint i = 0; i < _party.size(); ++i)
+ _party[i]->_canAttack = true;
+
setupAttackerVal();
}
void Combat::setupAttackerVal() {
_attackerVal = 0;
for (uint i = 0; i < _party.size(); ++i) {
- if (_canAttack[i])
+ if (_party[i]->_canAttack)
++_attackerVal;
}
@@ -174,14 +182,14 @@ void Combat::setupAttackerVal() {
void Combat::checkLeftWall() {
Maps::Maps &maps = *g_maps;
- _canAttack[2] = !(maps._currentWalls & maps._leftMask) ||
+ _party[2]->_canAttack = !(maps._currentWalls & maps._leftMask) ||
getRandomNumber(100) <= 25;
}
void Combat::checkRightWall() {
Maps::Maps &maps = *g_maps;
- _canAttack[3] = !(maps._currentWalls & maps._rightMask) ||
+ _party[3]->_canAttack = !(maps._currentWalls & maps._rightMask) ||
getRandomNumber(100) <= 25;
}
@@ -436,7 +444,8 @@ void Combat::nextRound3() {
}
void Combat::clearArrays() {
- Common::fill(&_arr3[0], &_arr3[MAX_PARTY_SIZE], 0);
+ for (uint i = 0; i < _party.size(); ++i)
+ _party[i]->_combat3 = 0;
for (uint i = 0; i < _monsterList.size(); ++i)
_monsterList[i]._checked = 0;
@@ -690,7 +699,7 @@ void Combat::checkParty() {
for (uint i = 0; i < _party.size(); ++i) {
const Character &c = *_party[i];
if ((c._condition & BAD_CONDITION) || !c._hpBase)
- _arr3[i] = 1;
+ _party[i]->_combat3 = 1;
}
loop1();
@@ -827,7 +836,7 @@ void Combat::attackMonster(int monsterNum) {
_message.push_back(Line(0, 1, STRING["dialogs.combat.weapon_no_effect"]));
}
- _arr3[_currentChar] = 1;
+ _party[_currentChar]->_combat3 = 1;
setMode(CHAR_ATTACKS);
}
@@ -1037,7 +1046,7 @@ void Combat::iterateMonsters2Inner() {
}
void Combat::updateArr3() {
- _arr3[_currentChar] = 1;
+ _party[_currentChar]->_combat3 = 1;
combatLoop();
}
@@ -1049,7 +1058,7 @@ void Combat::resetDestMonster() {
}
void Combat::spellFailed() {
- _arr3[_currentChar] = 1;
+ _party[_currentChar]->_combat3 = 1;
SoundMessage msg(10, 2, Common::String::format("*** %s ***",
STRING["spells.failed"].c_str()));
@@ -1089,7 +1098,7 @@ void Combat::turnUndead() {
displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
}
- _arr3[_currentChar] = 1;
+ _party[_currentChar]->_combat3 = 1;
}
void Combat::destroyMonster() {
@@ -1201,7 +1210,7 @@ void Combat::holyWord() {
displaySpellResult(InfoMessage(5, 1, STRING["spells.monsters_destroyed"]));
else
displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
- _arr3[_currentChar] = 1;
+ _party[_currentChar]->_combat3 = 1;
}
#define COL2 21
@@ -1247,7 +1256,7 @@ void Combat::identifyMonster() {
msg._lines.push_back(Line(0, 3, line));
msg._timeoutCallback = []() {
- g_globals->_combat->_arr3[g_globals->_combat->_currentChar] = 1;
+ g_globals->_combat->_party[g_globals->_combat->_currentChar]->_combat3 = 1;
g_globals->_combat->combatLoop();
};
@@ -1290,8 +1299,8 @@ void Combat::lightningBolt() {
}
void Combat::makeRoom() {
- for (int i = 0; i < 5; ++i)
- _canAttack[i] = 1;
+ for (uint i = 0; i < MIN(_party.size(), 5U); ++i)
+ _party[i]->_canAttack = true;
}
void Combat::slow() {
@@ -1375,7 +1384,7 @@ void Combat::fingerOfDeath() {
InfoMessage msg(0, 0, line1, 0, 2, line2);
msg._delaySeconds = 3;
msg._timeoutCallback = []() {
- g_globals->_combat->_arr3[g_globals->_combat->_currentChar] = 1;
+ g_globals->_combat->_party[g_globals->_combat->_currentChar]->_combat3 = 1;
g_globals->_combat->combatLoop();
};
@@ -1406,7 +1415,7 @@ void Combat::disintegration() {
InfoMessage msg(0, 0, line1, 0, 2, line2);
msg._delaySeconds = 3;
msg._timeoutCallback = []() {
- g_globals->_combat->_arr3[g_globals->_combat->_currentChar] = 1;
+ g_globals->_combat->_party[g_globals->_combat->_currentChar]->_combat3 = 1;
g_globals->_combat->combatLoop();
};
@@ -1471,7 +1480,7 @@ void Combat::selectMonsterTarget() {
// Find a party position that can attack
int wrapCount = 0;
- while (!_canAttack[idx]) {
+ while (!_party[idx]->_canAttack) {
if (++idx >= g_globals->_party.size()) {
idx = 0;
if (++wrapCount > 1)
@@ -1494,8 +1503,8 @@ void Combat::selectMonsterTarget() {
// At this point, fall back on a generic display message
// that the monster infiltrates the ranks, which basically
// means enabling the whole party to be able to attack directly
- for (int i = 0; i < 6; ++i)
- _canAttack[i] = true;
+ for (uint i = 0; i < _party.size(); ++i)
+ _party[i]->_canAttack = true;
_attackerVal = g_globals->_party.size() * 2;
setMode(INFILTRATION);
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 9053b39b358..80bddc7d348 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -39,8 +39,6 @@ protected:
int _monstersCount = 0;
Common::Array<Character *> _party;
Monster *_monsterP;
- int _arr3[MAX_PARTY_SIZE / 2];
- bool _canAttack[MAX_PARTY_SIZE];
bool _treasureFlags[MAX_PARTY_SIZE];
int _val1;
int _roundNum;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 52715c6d4aa..918e4e25476 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -339,7 +339,7 @@ void Combat::writeAllOptions() {
break;
}
- bool canAttack = _canAttack[_currentChar];
+ bool canAttack = _party[_currentChar]->_canAttack;
if (canAttack) {
writeAttackOptions();
_allowAttack = true;
@@ -446,7 +446,7 @@ void Combat::writeRound() {
void Combat::writePartyNumbers() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
writeChar(2 + 4 * (i % 2), 3 + (i / 2),
- _canAttack[i] ? '+' : ' ');
+ _party[i]->_canAttack ? '+' : ' ');
writeChar('1' + i);
}
}
Commit: dc5e5b2a7b01f4519ad36f60576750c4ce8a473d
https://github.com/scummvm/scummvm/commit/dc5e5b2a7b01f4519ad36f60576750c4ce8a473d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Minor cleanup
Changed paths:
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 918e4e25476..e189c877678 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -444,7 +444,7 @@ void Combat::writeRound() {
}
void Combat::writePartyNumbers() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ for (uint i = 0; i < _party.size(); ++i) {
writeChar(2 + 4 * (i % 2), 3 + (i / 2),
_party[i]->_canAttack ? '+' : ' ');
writeChar('1' + i);
@@ -506,7 +506,7 @@ void Combat::writeDots() {
void Combat::writeParty() {
clearPartyArea();
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ for (uint i = 0; i < _party.size(); ++i) {
writeChar(1 + 21 * (i % 2), 16 + (i / 2), '1' + i);
writeString(") ");
writeString(g_globals->_party[i]._name);
Commit: d3a8ce091fff332184a98431fdff2757270743f2
https://github.com/scummvm/scummvm/commit/d3a8ce091fff332184a98431fdff2757270743f2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Implement in-combat retreat
Changed paths:
engines/mm/mm1/data/treasure.cpp
engines/mm/mm1/data/treasure.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/data/treasure.cpp b/engines/mm/mm1/data/treasure.cpp
index 63b38aeb769..730678cf2d4 100644
--- a/engines/mm/mm1/data/treasure.cpp
+++ b/engines/mm/mm1/data/treasure.cpp
@@ -32,6 +32,10 @@ void Treasure::clear() {
Common::fill(&_data[0], &_data[ARRAY_COUNT], 0);
}
+void Treasure::clear0() {
+ Common::fill(&_data[1], &_data[ARRAY_COUNT], 0);
+}
+
byte &Treasure::operator[](uint i) {
assert(i < ARRAY_COUNT);
return _data[i];
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
index 0a54dc7d488..680b3706f52 100644
--- a/engines/mm/mm1/data/treasure.h
+++ b/engines/mm/mm1/data/treasure.h
@@ -54,6 +54,11 @@ public:
*/
void clear();
+ /**
+ * Clears everything byte byte 0
+ */
+ void clear0();
+
/**
* Returns true if any treasure has been assigned
*/
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 2c1e56b3475..30bb88409b1 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1510,6 +1510,29 @@ void Combat::selectMonsterTarget() {
setMode(INFILTRATION);
}
+void Combat::retreat() {
+ Encounter &enc = g_globals->_encounters;
+
+ if (getRandomNumber(100) <= enc._fleeThreshold ||
+ getRandomNumber(100) < _roundNum) {
+ Maps::Maps &maps = g_globals->_maps;
+ Maps::Map &map = *maps._currentMap;
+ maps._mapPos = Common::Point(map[Maps::MAP_FLEE_X],
+ map[Maps::MAP_FLEE_Y]);
+
+ g_globals->_treasure.clear0();
+ combatDone();
+
+ } else {
+ if (enc._fleeThreshold)
+ // Increase threshold to gradually make it easier to flee
+ enc._fleeThreshold++;
+
+ _party[_currentChar]->_combat3 = true;
+ combatLoop();
+ }
+}
+
void Combat::combatDone() {
// Reset several active spells
g_globals->_activeSpells._s.bless = 0;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 80bddc7d348..7f6a72d8946 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -259,6 +259,11 @@ protected:
*/
void selectMonsterTarget();
+ /**
+ * Retreat option
+ */
+ void retreat();
+
/**
* Does final cleanup when combat is done
*/
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index e189c877678..8dfb2a3a334 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -690,9 +690,6 @@ void Combat::fight() {
}
}
-void Combat::retreat() {
-}
-
void Combat::shoot() {
if (_allowShoot) {
if (_monsterList.size() < 2) {
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 673c2691d61..07c1bab10a0 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -173,11 +173,6 @@ private:
*/
void fight();
- /**
- * Retreat option
- */
- void retreat();
-
/**
* Shoot option
*/
Commit: 1a7e3f44358d07e38f43ce2ac3a19479201cc6d9
https://github.com/scummvm/scummvm/commit/1a7e3f44358d07e38f43ce2ac3a19479201cc6d9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Rename Character _arr3 to _checked
Changed paths:
engines/mm/mm1/data/character.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index d057b342a7d..bf62e4ea502 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -449,7 +449,7 @@ struct Character : public PrimaryAttributes {
// Non persistent fields
byte _numDrinks = 0;
// Combat fields
- byte _combat3 = 0;
+ bool _checked = false;
bool _canAttack = false;
Character();
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 30bb88409b1..71d764256bd 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -42,7 +42,7 @@ void Combat::clear() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._combat3 = 0;
+ c._checked = false;
c._canAttack = false;
}
@@ -445,10 +445,10 @@ void Combat::nextRound3() {
void Combat::clearArrays() {
for (uint i = 0; i < _party.size(); ++i)
- _party[i]->_combat3 = 0;
+ _party[i]->_checked = false;
for (uint i = 0; i < _monsterList.size(); ++i)
- _monsterList[i]._checked = 0;
+ _monsterList[i]._checked = false;
}
void Combat::updateHighestLevel() {
@@ -699,7 +699,7 @@ void Combat::checkParty() {
for (uint i = 0; i < _party.size(); ++i) {
const Character &c = *_party[i];
if ((c._condition & BAD_CONDITION) || !c._hpBase)
- _party[i]->_combat3 = 1;
+ _party[i]->_checked = true;
}
loop1();
@@ -836,7 +836,7 @@ void Combat::attackMonster(int monsterNum) {
_message.push_back(Line(0, 1, STRING["dialogs.combat.weapon_no_effect"]));
}
- _party[_currentChar]->_combat3 = 1;
+ _party[_currentChar]->_checked = true;
setMode(CHAR_ATTACKS);
}
@@ -1038,15 +1038,15 @@ void Combat::iterateMonsters2Inner() {
};
} else {
msg._ynCallback = []() {
- g_globals->_combat->updateArr3();
+ g_globals->_combat->characterDone();
};
}
displaySpellResult(msg);
}
-void Combat::updateArr3() {
- _party[_currentChar]->_combat3 = 1;
+void Combat::characterDone() {
+ _party[_currentChar]->_checked = true;
combatLoop();
}
@@ -1058,7 +1058,7 @@ void Combat::resetDestMonster() {
}
void Combat::spellFailed() {
- _party[_currentChar]->_combat3 = 1;
+ _party[_currentChar]->_checked = true;
SoundMessage msg(10, 2, Common::String::format("*** %s ***",
STRING["spells.failed"].c_str()));
@@ -1098,7 +1098,7 @@ void Combat::turnUndead() {
displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
}
- _party[_currentChar]->_combat3 = 1;
+ _party[_currentChar]->_checked = true;
}
void Combat::destroyMonster() {
@@ -1210,7 +1210,7 @@ void Combat::holyWord() {
displaySpellResult(InfoMessage(5, 1, STRING["spells.monsters_destroyed"]));
else
displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
- _party[_currentChar]->_combat3 = 1;
+ _party[_currentChar]->_checked = true;
}
#define COL2 21
@@ -1256,8 +1256,7 @@ void Combat::identifyMonster() {
msg._lines.push_back(Line(0, 3, line));
msg._timeoutCallback = []() {
- g_globals->_combat->_party[g_globals->_combat->_currentChar]->_combat3 = 1;
- g_globals->_combat->combatLoop();
+ g_globals->_combat->characterDone();
};
displaySpellResult(msg);
@@ -1384,8 +1383,7 @@ void Combat::fingerOfDeath() {
InfoMessage msg(0, 0, line1, 0, 2, line2);
msg._delaySeconds = 3;
msg._timeoutCallback = []() {
- g_globals->_combat->_party[g_globals->_combat->_currentChar]->_combat3 = 1;
- g_globals->_combat->combatLoop();
+ g_globals->_combat->characterDone();
};
displaySpellResult(msg);
@@ -1415,8 +1413,7 @@ void Combat::disintegration() {
InfoMessage msg(0, 0, line1, 0, 2, line2);
msg._delaySeconds = 3;
msg._timeoutCallback = []() {
- g_globals->_combat->_party[g_globals->_combat->_currentChar]->_combat3 = 1;
- g_globals->_combat->combatLoop();
+ g_globals->_combat->characterDone();
};
displaySpellResult(msg);
@@ -1528,8 +1525,7 @@ void Combat::retreat() {
// Increase threshold to gradually make it easier to flee
enc._fleeThreshold++;
- _party[_currentChar]->_combat3 = true;
- combatLoop();
+ g_globals->_combat->characterDone();
}
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 7f6a72d8946..b654c630a5f 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -275,7 +275,7 @@ private:
bool monsterLevelThreshold() const;
void iterateMonsters1Inner();
void iterateMonsters2Inner();
- void updateArr3();
+ void characterDone();
void summonLightning2();
void fireball2();
void levelAdjust();
Commit: ba3acbbb7073b8827a02bec0995cbb277337e1e5
https://github.com/scummvm/scummvm/commit/ba3acbbb7073b8827a02bec0995cbb277337e1e5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Display combat spell results
Changed paths:
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index b654c630a5f..311bae83e55 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -73,7 +73,7 @@ protected:
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL,
CHAR_ATTACKS, MONSTER_ATTACK, INFILTRATION,
- WAITS_FOR_OPENING
+ WAITS_FOR_OPENING, SPELL_RESULT
};
Mode _mode = SELECT_OPTION;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 8dfb2a3a334..6cb0cd0b745 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -144,6 +144,12 @@ void Combat::draw() {
delaySeconds(5);
break;
+ case SPELL_RESULT:
+ writeSpellResult();
+ if (_spellResult._delaySeconds)
+ delaySeconds(_spellResult._delaySeconds);
+ break;
+
default:
break;
}
@@ -153,30 +159,30 @@ void Combat::timeout() {
switch (_mode) {
case NEXT_ROUND:
nextRound2();
- return;
+ break;
case MONSTER_ADVANCES:
nextRound3();
- return;
+ break;
case MONSTERS_AFFECTED:
case CHAR_ATTACKS:
combatLoop();
- return;
+ break;
case MONSTER_FLEES:
checkMonsterSpells();
- return;
+ break;
case MONSTER_WANDERS:
case INFILTRATION:
case MONSTER_ATTACK:
writeParty();
writeMonsters();
checkParty();
- return;
+ break;
case MONSTER_SPELL:
checkMonsterSpellDone();
- return;
+ break;
case WAITS_FOR_OPENING:
loop1();
- return;
+ break;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_activeSpells;
spells._s.bless = 0;
@@ -186,13 +192,14 @@ void Combat::timeout() {
close();
g_events->send("Game", GameMessage("UPDATE"));
- return;
+ break;
}
+ case SPELL_RESULT:
+ _spellResult._timeoutCallback();
+ break;
default:
break;
}
-
-// redraw();
}
bool Combat::msgKeypress(const KeypressMessage &msg) {
@@ -225,6 +232,16 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
default:
break;
}
+ } else if (_mode == SPELL_RESULT && !isDelayActive()) {
+ // Displaying a spell result that required waiting for keypress
+ assert(_spellResult._timeoutCallback);
+ _spellResult._timeoutCallback();
+
+ } else if (isDelayActive()) {
+ // In all other modes, if a delay is active, any keypress
+ // will cause the delay to end immediately
+ cancelDelay();
+ timeout();
}
return true;
@@ -647,6 +664,13 @@ void Combat::writeWaitsForOpening() {
writeString(0, 20, line);
}
+void Combat::writeSpellResult() {
+ for (uint i = 0; i < _spellResult._lines.size(); ++i) {
+ const Line &l = _spellResult._lines[i];
+ writeString(l.x, l.y + 20, l._text);
+ }
+}
+
void Combat::checkMonsterSpellDone() {
for (uint i = 0; i < _monsterSpellLines.size(); ++i) {
if (i > 0 && _monsterSpellLines[i].y ==
@@ -779,9 +803,9 @@ void Combat::setOption(SelectedOption option) {
void Combat::displaySpellResult(const InfoMessage &msg) {
assert(msg._timeoutCallback || msg._keyCallback);
assert(!msg._delaySeconds || !msg._timeoutCallback);
+ _spellResult = msg;
- // TODO: Display the spell result
- warning("TODO: displaySpellResult");
+ setMode(SPELL_RESULT);
}
} // namespace Views
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 07c1bab10a0..79afe2c56b8 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -33,6 +33,7 @@ class Combat : public TextView, public Game::Combat {
private:
LineArray _monsterSpellLines;
uint _fightCount = 0;
+ InfoMessage _spellResult;
// Combat options that have sub-option selection
enum SelectedOption {
OPTION_NONE, OPTION_DELAY, OPTION_FIGHT,
@@ -138,6 +139,11 @@ private:
*/
void writeWaitsForOpening();
+ /**
+ * Writes the result of a spell
+ */
+ void writeSpellResult();
+
/**
* Whether there's messages remaining
*/
Commit: 7301dcd15fe859aa4f34be637c1f02cf58fb1663
https://github.com/scummvm/scummvm/commit/7301dcd15fe859aa4f34be637c1f02cf58fb1663
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Hopefully properly implement monsterAdvances
Changed paths:
engines/mm/mm1/data/treasure.h
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/data/treasure.h b/engines/mm/mm1/data/treasure.h
index 680b3706f52..f1fad603843 100644
--- a/engines/mm/mm1/data/treasure.h
+++ b/engines/mm/mm1/data/treasure.h
@@ -55,7 +55,7 @@ public:
void clear();
/**
- * Clears everything byte byte 0
+ * Clears everything except byte 0
*/
void clear0();
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 71d764256bd..febe0a7f3f2 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -485,9 +485,13 @@ bool Combat::moveMonsters() {
}
void Combat::monsterAdvances() {
- // TODO: Shouldn't placement changes affect the arrays
- _monsterList.remove_at(_advanceIndex);
- _monsterName = _monsterList[_advanceIndex]._name;
+ // TODO: I can't understand the advancement logic at all.
+ // So for now, I'm simply moving the monster forward one slot
+ assert(_advanceIndex > 0);
+ Monster mon = _monsterList.remove_at(_advanceIndex);
+ _monsterList.insert_at(_advanceIndex - 1, mon);
+
+ setMode(MONSTER_ADVANCES);
}
bool Combat::monsterChanges() {
@@ -1102,7 +1106,7 @@ void Combat::turnUndead() {
}
void Combat::destroyMonster() {
- _monsterList[getMonsterIndex()]._status = 0xff;
+ _monsterList[getMonsterIndex()]._status = MONFLAG_DEAD;
Sound::sound2(SOUND_9);
}
Commit: f814fd681b02a0358d1ded18ef13cda48590b44d
https://github.com/scummvm/scummvm/commit/f814fd681b02a0358d1ded18ef13cda48590b44d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Fix _monsterP in monsterAdvances
Changed paths:
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index febe0a7f3f2..db56577ea10 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -490,6 +490,7 @@ void Combat::monsterAdvances() {
assert(_advanceIndex > 0);
Monster mon = _monsterList.remove_at(_advanceIndex);
_monsterList.insert_at(_advanceIndex - 1, mon);
+ _monsterP = &_monsterList[_advanceIndex - 1];
setMode(MONSTER_ADVANCES);
}
Commit: ce6c698d2e61de870b9f4304f3807bb751b98503
https://github.com/scummvm/scummvm/commit/ce6c698d2e61de870b9f4304f3807bb751b98503
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Hook up CastSpell view for in-combat spell casting
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/game/spell_casting.h
engines/mm/mm1/messages.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index db56577ea10..0dc5748b359 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1512,6 +1512,14 @@ void Combat::selectMonsterTarget() {
setMode(INFILTRATION);
}
+void Combat::block() {
+ // TODO
+}
+
+void Combat::cast() {
+ g_events->addView("CastSpell");
+}
+
void Combat::retreat() {
Encounter &enc = g_globals->_encounters;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 311bae83e55..f469804b036 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -259,6 +259,17 @@ protected:
*/
void selectMonsterTarget();
+
+ /**
+ * Block option
+ */
+ void block();
+
+ /**
+ * Cast option
+ */
+ void cast();
+
/**
* Retreat option
*/
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 56db41444c7..ec213f90b2b 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -146,6 +146,9 @@ Common::String SpellCasting::getSpellError() const {
case SS_COMBAT_ONLY:
msg = STRING["spells.combat_only"];
break;
+ case SS_NONCOMBAT_ONLY:
+ msg = STRING["spells.noncombat_only"];
+ break;
case SS_OUTDOORS_ONLY:
msg = STRING["spells.outdoors_only"];
break;
diff --git a/engines/mm/mm1/game/spell_casting.h b/engines/mm/mm1/game/spell_casting.h
index 383db8287f0..ce903fc4836 100644
--- a/engines/mm/mm1/game/spell_casting.h
+++ b/engines/mm/mm1/game/spell_casting.h
@@ -38,15 +38,16 @@ enum SpellState {
* Support class for handling spell casting logic
*/
class SpellCasting {
-private:
- /**
- * Returns true if combat is in progress
- */
- bool isInCombat() const;
protected:
int _spellIndex = 0;
int _requiredSp = 0, _requiredGems = 0;
SpellState _spellState = SS_OK;
+
+ /**
+ * Returns true if combat is in progress
+ */
+ bool isInCombat() const;
+
public:
/**
* Sets the current spell
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index c684771a920..d25e4372dac 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -74,13 +74,15 @@ struct MouseUpMessage : public MouseMessage {
struct GameMessage : public Message {
Common::String _name;
int _value;
+ Common::String _stringValue;
- GameMessage() : Message() {}
+ GameMessage() : Message(), _value(-1) {}
GameMessage(const Common::String &name) : Message(),
_name(name), _value(-1) {}
GameMessage(const Common::String &name, int value) : Message(),
- _name(name), _value(value) {
- }
+ _name(name), _value(value) {}
+ GameMessage(const Common::String &name, const Common::String &value) :
+ Message(), _name(name), _stringValue(value) {}
};
struct HeaderMessage : public Message {
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 6cb0cd0b745..9389c2a9e68 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -76,6 +76,15 @@ bool Combat::msgUnfocus(const UnfocusMessage &msg) {
return TextView::msgUnfocus(msg);
}
+bool Combat::msgGame(const GameMessage &msg) {
+ if (msg._name == "SPELL_RESULT") {
+ displaySpellResult(msg._stringValue);
+ return true;
+ }
+
+ return false;
+}
+
void Combat::draw() {
switch (_mode) {
case NEXT_ROUND:
@@ -691,12 +700,6 @@ void Combat::attack() {
attackMonsterPhysical();
}
-void Combat::block() {
-}
-
-void Combat::cast() {
-}
-
void Combat::delay() {
setOption(OPTION_DELAY);
}
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 79afe2c56b8..899bfd0b9e5 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -154,16 +154,6 @@ private:
*/
void attack();
- /**
- * Block option
- */
- void block();
-
- /**
- * Cast option
- */
- void cast();
-
/**
* Delay option
*/
@@ -246,6 +236,11 @@ public:
*/
bool msgUnfocus(const UnfocusMessage &msg) override;
+ /**
+ * Called for game messages
+ */
+ bool msgGame(const GameMessage &msg) override;
+
/**
* Draw the Combat details overlayed on
* the existing game screen
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index df807ac7249..cb4edf0a4e7 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -226,11 +226,17 @@ void CastSpell::spellDone() {
}
void CastSpell::spellDone(const Common::String &msg, int xp) {
- _state = ENDING;
- Sound::sound(SOUND_2);
- clearSurface();
- writeString(xp, 1, msg);
- delaySeconds(3);
+ if (isInCombat()) {
+ close();
+ g_events->focusedView()->send(GameMessage("SPELL_RESULT", msg));
+
+ } else {
+ _state = ENDING;
+ Sound::sound(SOUND_2);
+ clearSurface();
+ writeString(xp, 1, msg);
+ delaySeconds(3);
+ }
}
} // namespace Spells
Commit: 40c1082940d6a93a02c4056ccc153ef168dd1fb0
https://github.com/scummvm/scummvm/commit/40c1082940d6a93a02c4056ccc153ef168dd1fb0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: More combat actions implemented
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index ae1a19059bf..398c3777ca2 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -389,6 +389,7 @@
set_delay: "SET DELAY (0-9):"
delay_currently: "(CURRENTLY= %d)"
infiltration: "INFILTRATES THE RANKS!"
+ exchange_places: "EXCHANGE PLACES WITH (1-%c)?"
status:
0: "(PARALYZE)"
1: "(WEBBED) "
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 0dc5748b359..f2b979790b3 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1512,19 +1512,35 @@ void Combat::selectMonsterTarget() {
setMode(INFILTRATION);
}
+void Combat::attack() {
+ if (_allowAttack)
+ attackMonsterPhysical();
+}
+
void Combat::block() {
- // TODO
+ characterDone();
}
void Combat::cast() {
g_events->addView("CastSpell");
}
+void Combat::exchangeWith(int charNum) {
+ _party[_currentChar]->_checked = true;
+ Character *c1 = _party[_currentChar];
+ Character *c2 = _party[charNum];
+ _party[_currentChar] = c2;
+ _party[charNum] = c1;
+
+ _currentChar = charNum;
+ combatLoop();
+}
+
void Combat::retreat() {
Encounter &enc = g_globals->_encounters;
if (getRandomNumber(100) <= enc._fleeThreshold ||
- getRandomNumber(100) < _roundNum) {
+ getRandomNumber(100) < _roundNum) {
Maps::Maps &maps = g_globals->_maps;
Maps::Map &map = *maps._currentMap;
maps._mapPos = Common::Point(map[Maps::MAP_FLEE_X],
@@ -1542,6 +1558,11 @@ void Combat::retreat() {
}
}
+void Combat::use() {
+ // Show the character info view in USE mode
+ g_events->send("CharacterInfo", GameMessage("USE"));
+}
+
void Combat::combatDone() {
// Reset several active spells
g_globals->_activeSpells._s.bless = 0;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index f469804b036..a63580ec48d 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -260,6 +260,11 @@ protected:
void selectMonsterTarget();
+ /**
+ * Attack option
+ */
+ void attack();
+
/**
* Block option
*/
@@ -270,6 +275,16 @@ protected:
*/
void cast();
+ /**
+ * Exchange current character with another
+ */
+ void exchangeWith(int charNum);
+
+ /**
+ * Use option
+ */
+ void use();
+
/**
* Retreat option
*/
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 9389c2a9e68..e591b2a97ab 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -257,7 +257,8 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
}
bool Combat::msgAction(const ActionMessage &msg) {
- if (_mode != SELECT_OPTION || _option != OPTION_NONE)
+ if (_mode != SELECT_OPTION || (_option != OPTION_NONE &&
+ _option != OPTION_EXCHANGE))
return false;
switch (msg._action) {
@@ -269,8 +270,13 @@ bool Combat::msgAction(const ActionMessage &msg) {
case KEYBIND_VIEW_PARTY6: {
uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
if (charNum < _party.size()) {
- g_globals->_currCharacter = _party[charNum];
- addView("CharacterInfo");
+ if (_option == OPTION_EXCHANGE) {
+ if (_party[charNum] != g_globals->_currCharacter)
+ exchangeWith(charNum);
+ } else {
+ g_globals->_currCharacter = _party[charNum];
+ addView("CharacterInfo");
+ }
return true;
}
break;
@@ -309,6 +315,12 @@ bool Combat::msgAction(const ActionMessage &msg) {
case KEYBIND_COMBAT_USE:
use();
break;
+ case KEYBIND_ESCAPE:
+ if (_mode == SELECT_OPTION) {
+ _option = OPTION_NONE;
+ combatLoop();
+ }
+ break;
default:
// TODO: Character and quickref views
break;
@@ -327,6 +339,9 @@ void Combat::writeOptions() {
case OPTION_DELAY:
writeDelaySelect();
break;
+ case OPTION_EXCHANGE:
+ writeExchangeSelect();
+ break;
case OPTION_FIGHT:
writeFightSelect();
break;
@@ -397,6 +412,14 @@ void Combat::writeDelaySelect() {
escToGoBack(0, 3);
}
+void Combat::writeExchangeSelect() {
+ resetBottom();
+ writeString(7, 20, Common::String::format(
+ STRING["dialogs.combat.exchange_places"].c_str(),
+ '0' + _party.size()));
+ escToGoBack(12, 23);
+}
+
void Combat::writeFightSelect() {
_fightCount = MIN(_attackerVal, (int)_monsterList.size());
@@ -695,16 +718,13 @@ void Combat::checkMonsterSpellDone() {
checkParty();
}
-void Combat::attack() {
- if (_allowAttack)
- attackMonsterPhysical();
-}
-
void Combat::delay() {
setOption(OPTION_DELAY);
}
void Combat::exchange() {
+ if (_party.size() > 1)
+ setOption(OPTION_EXCHANGE);
}
void Combat::fight() {
@@ -727,11 +747,6 @@ void Combat::shoot() {
}
}
-void Combat::use() {
- // Show the character info view in USE mode
- g_events->send("CharacterInfo", GameMessage("USE"));
-}
-
void Combat::writeMessage() {
size_t idx;
@@ -799,7 +814,9 @@ Common::String Combat::getAttackString() {
}
void Combat::setOption(SelectedOption option) {
- MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ MetaEngine::setKeybindingMode((option == OPTION_EXCHANGE) ?
+ KeybindingMode::KBMODE_PARTY_MENUS :
+ KeybindingMode::KBMODE_MENUS);
_option = option;
}
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 899bfd0b9e5..bc6ab71d8b9 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -36,8 +36,8 @@ private:
InfoMessage _spellResult;
// Combat options that have sub-option selection
enum SelectedOption {
- OPTION_NONE, OPTION_DELAY, OPTION_FIGHT,
- OPTION_SHOOT
+ OPTION_NONE, OPTION_DELAY, OPTION_EXCHANGE,
+ OPTION_FIGHT, OPTION_SHOOT
};
SelectedOption _option = OPTION_NONE;
@@ -149,11 +149,6 @@ private:
*/
void checkMonsterSpellDone();
- /**
- * Attack option
- */
- void attack();
-
/**
* Delay option
*/
@@ -174,11 +169,6 @@ private:
*/
void shoot();
- /**
- * Use option
- */
- void use();
-
/**
* Write message for characters attacking monsters
*/
@@ -199,6 +189,11 @@ private:
*/
void writeDelaySelect();
+ /**
+ * Write text for exchange party member
+ */
+ void writeExchangeSelect();
+
/**
* Having selected to fight, selects monster to attack
*/
Commit: 2014e4d24a76fdad291ea2ee4c6f71a8be35172c
https://github.com/scummvm/scummvm/commit/2014e4d24a76fdad291ea2ee4c6f71a8be35172c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:40+01:00
Commit Message:
MM: MM1: Fleshing out combat_val2 as _activeMonsterNum
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index f2b979790b3..fea3e0eb485 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -53,7 +53,7 @@ void Combat::clear() {
_val6 = _val7 = 0;
_partyIndex = _val9 = 0;
_val10 = _destCharCtr = 0;
- _val2 = 0;
+ _activeMonsterNum = 0;
_destAC = 0;
_numberOfTimes = 0;
_attackerLevel = 0;
@@ -573,6 +573,8 @@ void Combat::checkMonsterFlees() {
const Encounter &enc = g_globals->_encounters;
byte bitset = _monsterP->_field1e;
int threshold = -1;
+
+ _activeMonsterNum = _monsterIndex;
_monsterName = _monsterP->_name;
monsterIndexOf();
@@ -643,7 +645,7 @@ void Combat::checkMonsterActions() {
return;
_destCharCtr = 0;
- if (_val2 < _attackerVal) {
+ if (_activeMonsterNum < _attackerVal) {
selectMonsterTarget();
return;
}
@@ -735,7 +737,8 @@ void Combat::attackMonsterShooting() {
}
void Combat::attackMonster(int monsterNum) {
- monsterSetPtr(0);
+ _activeMonsterNum = monsterNum;
+ monsterSetPtr(monsterNum);
Character &c = *g_globals->_currCharacter;
_attackerLevel = c._level._current;
@@ -865,6 +868,7 @@ void Combat::updateMonsterStatus() {
if (val <= 0) {
_monsterList[_monsterIndex]._hp = 0;
_monsterList[_monsterIndex]._status = MONFLAG_DEAD;
+ warning("TODO: message that monster goes down");
} else {
_monsterList[_monsterIndex]._hp = val;
_monsterList[_monsterIndex]._status &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index a63580ec48d..3025efa6345 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -46,7 +46,7 @@ protected:
bool _allowFight, _allowShoot, _allowCast, _allowAttack;
byte _val6, _val7;
int _partyIndex, _val9, _val10;
- int _val2;
+ int _activeMonsterNum;
int _destCharCtr;
int _destAC;
int _numberOfTimes;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index e591b2a97ab..44b6c7221e8 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -508,7 +508,12 @@ void Combat::writeMonsters() {
for (int i = 0; i < (int)_monsterList.size(); ++i) {
_textPos = Common::Point(11, i);
writeChar(i < _attackerVal ? '+' : ' ');
- writeChar('A' + i);
+ unsigned char c = 'A' + i;
+ if ((i == _activeMonsterNum) && (_mode == MONSTER_ADVANCES ||
+ _mode == MONSTER_ATTACK || _mode == MONSTER_SPELL))
+ c |= 0x80;
+
+ writeChar(c);
writeString(") ");
writeString(_monsterList[i]._name);
writeMonsterStatus(i);
Commit: f8547ef7846a3e85ac2160a35c626dccc770ef2c
https://github.com/scummvm/scummvm/commit/f8547ef7846a3e85ac2160a35c626dccc770ef2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Cleanup of title screen, EGA palette, and screen decoder
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/gfx/gfx.cpp
engines/mm/mm1/gfx/gfx.h
engines/mm/mm1/gfx/screen_decoder.cpp
engines/mm/mm1/gfx/screen_decoder.h
engines/mm/mm1/mm1.cpp
engines/mm/mm1/views/title.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index c2d36044be4..6734d5175b9 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -52,12 +52,7 @@ void Events::runGame() {
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot == -1 ||
g_engine->loadGameState(saveSlot).getCode() != Common::kNoError) {
- // ***DEBUG*** start directly in-game
- for (uint i = 0; i < 6; ++i)
- g_globals->_party.push_back(g_globals->_roster[i]);
- g_globals->_maps.loadTown(Maps::SORPIGAL);
- msgGame(GameMessage("UPDATE"));
- //addView("Title");
+ addView("Title");
}
Common::Event e;
diff --git a/engines/mm/mm1/gfx/gfx.cpp b/engines/mm/mm1/gfx/gfx.cpp
index 158f6ab6145..6d97dfc6132 100644
--- a/engines/mm/mm1/gfx/gfx.cpp
+++ b/engines/mm/mm1/gfx/gfx.cpp
@@ -20,6 +20,7 @@
*/
#include "common/system.h"
+#include "common/debug.h"
#include "graphics/palette.h"
#include "mm/mm1/gfx/gfx.h"
@@ -27,26 +28,22 @@ namespace MM {
namespace MM1 {
namespace Gfx {
-#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
-
-static const byte EGA_PALETTE[64][3] = {
- {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
- {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
- {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
- {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
- {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
- {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
- {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
- {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
+static const uint32 EGA_PALETTE[16] = {
+ 0x000000, 0x0000aa, 0x00aa00, 0x00aaaa,
+ 0xaa0000, 0xaa00aa, 0xaa5500, 0xaaaaaa,
+ 0x555555, 0x5555ff, 0x55ff55, 0x55ffff,
+ 0xff5555, 0xff55ff, 0xffff55, 0xffffff
};
-void GFX::setEgaPalette(int palNum) {
+void GFX::setEgaPalette() {
byte pal[16 * 3];
byte *pDest = pal;
- const byte *pSrc = &EGA_PALETTE[palNum * 16][0];
- for (int i = 0; i < 16 * 3; ++i, ++pSrc, ++pDest)
- *pDest = VGA_COLOR_TRANS(*pSrc);
+ for (int i = 0; i < 16; ++i) {
+ *pDest++ = (EGA_PALETTE[i] >> 16) & 0xff;
+ *pDest++ = (EGA_PALETTE[i] >> 8) & 0xff;
+ *pDest++ = EGA_PALETTE[i] & 0xff;
+ }
g_system->getPaletteManager()->setPalette(pal, 0, 16);
@@ -54,6 +51,34 @@ void GFX::setEgaPalette(int palNum) {
g_system->getPaletteManager()->setPalette((const byte *)&c, 255, 1);
}
+void GFX::findPalette() {
+ byte palette[256 * 3];
+ g_system->getPaletteManager()->grabPalette(palette, 0, 256);
+
+ for (int col = 0; col < 16; ++col) {
+ byte r = (EGA_PALETTE[col] >> 16) & 0xff;
+ byte g = (EGA_PALETTE[col] >> 8) & 0xff;
+ byte b = EGA_PALETTE[col] & 0xff;
+ int closestDiff = 0x7fffffff;
+ byte closest = 0;
+ const byte *pal = &palette[0];
+
+ for (int i = 0; i < 256; ++i, pal += 3) {
+ int diff = ABS((int)r - (int)pal[0]) +
+ ABS((int)g - (int)pal[1]) +
+ ABS((int)b - (int)pal[2]);
+ if (diff < closestDiff) {
+ closestDiff = diff;
+ closest = i;
+ }
+ }
+
+ debug("%.3d", closest);
+ }
+}
+
+
+
} // namespace Gfx
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/gfx/gfx.h b/engines/mm/mm1/gfx/gfx.h
index 9a10b171810..73d493e96cb 100644
--- a/engines/mm/mm1/gfx/gfx.h
+++ b/engines/mm/mm1/gfx/gfx.h
@@ -33,7 +33,17 @@ namespace Gfx {
class GFX {
public:
- static void setEgaPalette(int palNum);
+ /**
+ * Sets the EGA palette
+ */
+ static void setEgaPalette();
+
+ /**
+ * Internal method used for enhanced mode
+ * when I needed to figure out which Xeen
+ * colors most closely matched the EGA palette
+ */
+ static void findPalette();
};
} // namespace Gfx
diff --git a/engines/mm/mm1/gfx/screen_decoder.cpp b/engines/mm/mm1/gfx/screen_decoder.cpp
index dbcacc1d1e5..7798648191c 100644
--- a/engines/mm/mm1/gfx/screen_decoder.cpp
+++ b/engines/mm/mm1/gfx/screen_decoder.cpp
@@ -59,9 +59,6 @@ bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
int index = 0;
int imgSize = w * h / 4;
- byte indexes[4];
- getPaletteIndexes(indexes);
-
// Decompress the image bytes
int x = 0;
while (x < (w / 4) && !stream.eos()) {
@@ -94,40 +91,12 @@ bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
for (int i = 0; i < w * h / 4; ++i, ++srcP) {
v = *srcP;
for (int j = 0; j < 4; ++j, v <<= 2)
- *destP++ = indexes[v >> 6];
+ *destP++ = _indexes[v >> 6];
}
return true;
}
-void ScreenDecoder::getPaletteIndexes(byte indexes[4]) {
- byte pal[PALETTE_SIZE];
- g_system->getPaletteManager()->grabPalette(pal, 0, PALETTE_COUNT);
-
- indexes[0] = 0;
- indexes[1] = findPalette(pal, 168, 84, 0);
- indexes[2] = findPalette(pal, 252, 252, 84);
- indexes[3] = findPalette(pal, 0xff, 0xff, 0xff);
-}
-
-byte ScreenDecoder::findPalette(const byte *pal, byte r, byte g, byte b) {
- int closestDiff = 0x7fffffff;
- byte closest = 0;
-
- for (int i = 0; i < PALETTE_COUNT; ++i, pal += 3) {
- int diff = ABS((int)r - (int)pal[0]) +
- ABS((int)g - (int)pal[1]) +
- ABS((int)b - (int)pal[2]);
- if (diff < closestDiff) {
- closestDiff = diff;
- closest = i;
- }
- }
-
- return closest;
-}
-
-
} // namespace Gfx
} // End of namespace Xeen
} // End of namespace MM
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
index 75763ffa398..25ce9b1227c 100644
--- a/engines/mm/mm1/gfx/screen_decoder.h
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -32,9 +32,8 @@ namespace Gfx {
class ScreenDecoder : public Image::ImageDecoder {
private:
Graphics::Surface _surface;
-
- void getPaletteIndexes(byte indexes[4]);
- byte findPalette(const byte *pal, byte r, byte g, byte b);
+public:
+ byte _indexes[4] = { 0 }; // Palete indexes used
public:
ScreenDecoder() {}
~ScreenDecoder() override;
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index 8fc72ebfd85..ea88afe484f 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -77,14 +77,7 @@ bool MM1Engine::isEnhanced() const {
}
void MM1Engine::setupNormal() {
- byte pal[12];
- pal[0] = pal[1] = pal[2] = 0;
- pal[3] = 168; pal[4] = 84; pal[5] = 0;
- pal[6] = 252; pal[7] = 252; pal[8] = 84;
- pal[9] = pal[10] = pal[11] = 255;
-
- g_system->getPaletteManager()->setPalette(pal, 0, 3);
- g_system->getPaletteManager()->setPalette(&pal[9], 255, 1);
+ Gfx::GFX::setEgaPalette();
}
bool MM1Engine::setupEnhanced() {
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index ed5f6470704..3d07719c73f 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -30,6 +30,11 @@ namespace Views {
Title::Title() : UIElement("Title", g_engine) {
Gfx::ScreenDecoder decoder;
+ decoder._indexes[0] = 0;
+ decoder._indexes[1] = 2;
+ decoder._indexes[2] = 4;
+ decoder._indexes[3] = 15;
+
if (decoder.loadFile("screen0")) {
_surface.copyFrom(decoder.getSurface());
} else {
@@ -38,7 +43,7 @@ Title::Title() : UIElement("Title", g_engine) {
}
void Title::draw() {
- getSurface().copyFrom(_surface);
+ getSurface().blitFrom(_surface);
}
} // namespace Views
Commit: cb617fa82eb9fc1542e75c4136dfcc415f5a829b
https://github.com/scummvm/scummvm/commit/cb617fa82eb9fc1542e75c4136dfcc415f5a829b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Implement scroll in alternating title screen
Changed paths:
engines/mm/mm1/views/title.cpp
engines/mm/mm1/views/title.h
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index 3d07719c73f..8174e6edc68 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -28,22 +28,87 @@ namespace MM {
namespace MM1 {
namespace Views {
+#define FADE_SEGMENTS 20
+#define FADE_SEGMENT_X (SCREEN_W / 2 / FADE_SEGMENTS)
+#define FADE_SEGMENT_Y (SCREEN_H / 2 / FADE_SEGMENTS)
+
Title::Title() : UIElement("Title", g_engine) {
+}
+
+bool Title::msgFocus(const FocusMessage &msg) {
Gfx::ScreenDecoder decoder;
decoder._indexes[0] = 0;
decoder._indexes[1] = 2;
decoder._indexes[2] = 4;
decoder._indexes[3] = 15;
- if (decoder.loadFile("screen0")) {
- _surface.copyFrom(decoder.getSurface());
- } else {
- error("Could not load screen0");
+ for (int i = 0; i < SCREEN_COUNT; ++i) {
+ if (decoder.loadFile(
+ Common::String::format("screen%d", i))) {
+ _screens[i].copyFrom(decoder.getSurface());
+ } else {
+ error("Could not load title screen");
+ }
}
+
+ _screenNum = -1;
+ _fadeIndex = 0;
+
+ return true;
+}
+
+bool Title::msgUnfocus(const UnfocusMessage & msg) {
+ for (int i = 0; i < SCREEN_COUNT; ++i)
+ _screens[i].clear();
+
+ return true;
}
void Title::draw() {
- getSurface().blitFrom(_surface);
+ Graphics::ManagedSurface surf = getSurface();
+
+ if (_screenNum == -1) {
+ // Initially, display the entire first screen
+ surf.blitFrom(_screens[0]);
+
+ // Start up fading in the second one
+ _screenNum = 1;
+ _fadeIndex = 0;
+ delaySeconds(1);
+
+ } else if (_fadeIndex == 0) {
+ // Brief pause before starting next screen scroll in
+ delaySeconds(1);
+
+ } else if (_screenNum < 2) {
+ // Gradually displaying more of the next screen
+ int deltaX = _fadeIndex * FADE_SEGMENT_X;
+ int deltaY = _fadeIndex * FADE_SEGMENT_Y;
+
+ const Graphics::ManagedSurface &src = _screens[_screenNum];
+ const Common::Rect top(0, 0, SCREEN_W, deltaY);
+ const Common::Rect left(0, 0, deltaX, SCREEN_H);
+ const Common::Rect right(SCREEN_W - deltaX, 0, SCREEN_W, SCREEN_H);
+ const Common::Rect bottom(0, SCREEN_H - deltaY, SCREEN_W, SCREEN_H);
+
+ surf.blitFrom(src, top, top);
+ surf.blitFrom(src, left, left);
+ surf.blitFrom(src, right, right);
+ surf.blitFrom(src, bottom, bottom);
+
+ delayFrames(2);
+ }
+}
+
+void Title::timeout() {
+ if (_screenNum < 2) {
+ if (_fadeIndex++ == FADE_SEGMENTS) {
+ _screenNum = (_screenNum == 0) ? 1 : 0;
+ _fadeIndex = 0;
+ }
+
+ redraw();
+ }
}
} // namespace Views
diff --git a/engines/mm/mm1/views/title.h b/engines/mm/mm1/views/title.h
index f20d52b5702..a032afe8646 100644
--- a/engines/mm/mm1/views/title.h
+++ b/engines/mm/mm1/views/title.h
@@ -28,14 +28,36 @@ namespace MM {
namespace MM1 {
namespace Views {
+#define SCREEN_COUNT 2
+
class Title : public UIElement {
private:
- Graphics::ManagedSurface _surface;
+ Graphics::ManagedSurface _screens[SCREEN_COUNT];
+ int _screenNum = -1;
+ int _fadeIndex = 0;
public:
Title();
virtual ~Title() {}
+ /**
+ * Called when the screen is displayed
+ */
+ bool msgFocus(const FocusMessage &msg) override;
+
+ /**
+ * Called when the screen is hidden
+ */
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+
+ /**
+ * Draw the screen
+ */
void draw() override;
+
+ /**
+ * Delay timeout
+ */
+ void timeout() override;
};
} // namespace Views
Commit: 258bdacf60f55cc07f06af948d126d94ce294933
https://github.com/scummvm/scummvm/commit/258bdacf60f55cc07f06af948d126d94ce294933
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Implement title screen scene slideshow
Changed paths:
engines/mm/mm1/views/title.cpp
engines/mm/mm1/views/title.h
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index 8174e6edc68..48ca517337a 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -42,7 +42,12 @@ bool Title::msgFocus(const FocusMessage &msg) {
decoder._indexes[2] = 4;
decoder._indexes[3] = 15;
- for (int i = 0; i < SCREEN_COUNT; ++i) {
+ for (int i = 0; i < SCREENS_COUNT; ++i) {
+ if (i == 2) {
+ decoder._indexes[1] = 3;
+ decoder._indexes[2] = 5;
+ }
+
if (decoder.loadFile(
Common::String::format("screen%d", i))) {
_screens[i].copyFrom(decoder.getSurface());
@@ -58,7 +63,7 @@ bool Title::msgFocus(const FocusMessage &msg) {
}
bool Title::msgUnfocus(const UnfocusMessage & msg) {
- for (int i = 0; i < SCREEN_COUNT; ++i)
+ for (int i = 0; i < SCREENS_COUNT; ++i)
_screens[i].clear();
return true;
@@ -76,7 +81,7 @@ void Title::draw() {
_fadeIndex = 0;
delaySeconds(1);
- } else if (_fadeIndex == 0) {
+ } else if (_screenNum < 2 && _fadeIndex == 0) {
// Brief pause before starting next screen scroll in
delaySeconds(1);
@@ -97,6 +102,13 @@ void Title::draw() {
surf.blitFrom(src, bottom, bottom);
delayFrames(2);
+
+ } else {
+ // Scene screens
+ const Graphics::ManagedSurface &src = _screens[_screenNum];
+ surf.blitFrom(src);
+
+ delaySeconds(5);
}
}
@@ -106,11 +118,34 @@ void Title::timeout() {
_screenNum = (_screenNum == 0) ? 1 : 0;
_fadeIndex = 0;
}
+ } else {
+ if (++_screenNum >= SCREENS_COUNT) {
+ // Go back to alternating first two screens
+ _screenNum = -1;
+ _fadeIndex = 0;
+ }
+ }
+ redraw();
+}
+
+bool Title::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
+ // Show the main menu
+ g_events->replaceView("MainMenu");
+
+ } else if (msg.keycode == Common::KEYCODE_SPACE) {
+ // Start showing game screens slideshow
+ cancelDelay();
+ _screenNum = 2;
+ _fadeIndex = 0;
redraw();
}
+
+ return true;
}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/title.h b/engines/mm/mm1/views/title.h
index a032afe8646..068c7286f73 100644
--- a/engines/mm/mm1/views/title.h
+++ b/engines/mm/mm1/views/title.h
@@ -28,11 +28,11 @@ namespace MM {
namespace MM1 {
namespace Views {
-#define SCREEN_COUNT 2
+#define SCREENS_COUNT 10
class Title : public UIElement {
private:
- Graphics::ManagedSurface _screens[SCREEN_COUNT];
+ Graphics::ManagedSurface _screens[SCREENS_COUNT];
int _screenNum = -1;
int _fadeIndex = 0;
public:
@@ -58,6 +58,12 @@ public:
* Delay timeout
*/
void timeout() override;
+
+ /**
+ * Handles keypresses
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+
};
} // namespace Views
Commit: 3a5f3e5b198de9fe9adb552bbd0837468c61f239
https://github.com/scummvm/scummvm/commit/3a5f3e5b198de9fe9adb552bbd0837468c61f239
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Set decoder palette indexes for first map
Changed paths:
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index bb5137c5404..462f4b919c0 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -368,6 +368,11 @@ void Maps::loadTile() {
tiles.resize(RESOURCE_TILES_COUNT);
Gfx::ScreenDecoder decoder;
+ decoder._indexes[0] = 0;
+ decoder._indexes[1] = 6;
+ decoder._indexes[2] = 14;
+ decoder._indexes[3] = 15;
+
for (int i = 0; i < RESOURCE_TILES_COUNT; ++i) {
if (!decoder.loadStream(*entry,
TILE_WIDTHS[i], TILE_HEIGHTS[i]))
Commit: de92498b7fbec19e571c47ee7ea5f43146aaedcf
https://github.com/scummvm/scummvm/commit/de92498b7fbec19e571c47ee7ea5f43146aaedcf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Add green lines to game screen
Changed paths:
engines/mm/mm1/views/game.cpp
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index e19200ba9e5..1e1f68fd5f5 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -29,7 +29,7 @@ namespace Views {
Game::Game() : TextView("Game"),
_view(this), _commands(this), _messages(this), _party(this) {
- _view.setBounds(Common::Rect(0, 0, 245, 128));
+ _view.setBounds(Common::Rect(0, 0, 240, 128));
}
bool Game::msgFocus(const FocusMessage &msg) {
@@ -44,6 +44,9 @@ bool Game::msgUnfocus(const UnfocusMessage &msg) {
void Game::draw() {
clearSurface();
+ Graphics::ManagedSurface surf = getSurface();
+ surf.hLine(0, 128, 320, 2);
+ surf.vLine(240, 0, 128, 2);
}
bool Game::msgAction(const ActionMessage &msg) {
Commit: 5207f7da52b686f4a7ee44ff397ff1dde2985e73
https://github.com/scummvm/scummvm/commit/5207f7da52b686f4a7ee44ff397ff1dde2985e73
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Fix screen decoding for enhanced version
Changed paths:
engines/mm/mm1/gfx/gfx.cpp
engines/mm/mm1/gfx/gfx.h
engines/mm/mm1/gfx/screen_decoder.cpp
engines/mm/mm1/gfx/screen_decoder.h
engines/mm/mm1/mm1.cpp
diff --git a/engines/mm/mm1/gfx/gfx.cpp b/engines/mm/mm1/gfx/gfx.cpp
index 6d97dfc6132..79fc4541403 100644
--- a/engines/mm/mm1/gfx/gfx.cpp
+++ b/engines/mm/mm1/gfx/gfx.cpp
@@ -22,12 +22,15 @@
#include "common/system.h"
#include "common/debug.h"
#include "graphics/palette.h"
+#include "graphics/screen.h"
#include "mm/mm1/gfx/gfx.h"
namespace MM {
namespace MM1 {
namespace Gfx {
+byte EGA_INDEXES[EGA_PALETTE_COUNT];
+
static const uint32 EGA_PALETTE[16] = {
0x000000, 0x0000aa, 0x00aa00, 0x00aaaa,
0xaa0000, 0xaa00aa, 0xaa5500, 0xaaaaaa,
@@ -35,26 +38,27 @@ static const uint32 EGA_PALETTE[16] = {
0xff5555, 0xff55ff, 0xffff55, 0xffffff
};
+
void GFX::setEgaPalette() {
byte pal[16 * 3];
byte *pDest = pal;
- for (int i = 0; i < 16; ++i) {
+ for (int i = 0; i < EGA_PALETTE_COUNT; ++i) {
*pDest++ = (EGA_PALETTE[i] >> 16) & 0xff;
*pDest++ = (EGA_PALETTE[i] >> 8) & 0xff;
*pDest++ = EGA_PALETTE[i] & 0xff;
+ EGA_INDEXES[i] = i;
}
g_system->getPaletteManager()->setPalette(pal, 0, 16);
uint32 c = 0xffffffff;
g_system->getPaletteManager()->setPalette((const byte *)&c, 255, 1);
-}
-void GFX::findPalette() {
- byte palette[256 * 3];
- g_system->getPaletteManager()->grabPalette(palette, 0, 256);
+ // Set the EGA palette indexes to be themselves
+}
+void GFX::findPalette(const byte palette[256 * 3]) {
for (int col = 0; col < 16; ++col) {
byte r = (EGA_PALETTE[col] >> 16) & 0xff;
byte g = (EGA_PALETTE[col] >> 8) & 0xff;
@@ -73,12 +77,10 @@ void GFX::findPalette() {
}
}
- debug("%.3d", closest);
+ EGA_INDEXES[col] = closest;
}
}
-
-
} // namespace Gfx
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/gfx/gfx.h b/engines/mm/mm1/gfx/gfx.h
index 73d493e96cb..b99fbafdc7c 100644
--- a/engines/mm/mm1/gfx/gfx.h
+++ b/engines/mm/mm1/gfx/gfx.h
@@ -30,6 +30,9 @@ namespace Gfx {
#define SCREEN_W 320
#define SCREEN_H 200
+#define EGA_PALETTE_COUNT 16
+
+extern byte EGA_INDEXES[EGA_PALETTE_COUNT];
class GFX {
public:
@@ -39,11 +42,10 @@ public:
static void setEgaPalette();
/**
- * Internal method used for enhanced mode
- * when I needed to figure out which Xeen
- * colors most closely matched the EGA palette
+ * Called after the Xeen palette has been loaded, to determine
+ * which palette indexes most closely match the EGA colors
*/
- static void findPalette();
+ static void findPalette(const byte palette[256 * 3]);
};
} // namespace Gfx
diff --git a/engines/mm/mm1/gfx/screen_decoder.cpp b/engines/mm/mm1/gfx/screen_decoder.cpp
index 7798648191c..684ce60640c 100644
--- a/engines/mm/mm1/gfx/screen_decoder.cpp
+++ b/engines/mm/mm1/gfx/screen_decoder.cpp
@@ -23,6 +23,7 @@
#include "common/system.h"
#include "graphics/palette.h"
#include "graphics/screen.h"
+#include "mm/mm1/gfx/gfx.h"
#include "mm/mm1/gfx/screen_decoder.h"
namespace MM {
@@ -91,7 +92,7 @@ bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
for (int i = 0; i < w * h / 4; ++i, ++srcP) {
v = *srcP;
for (int j = 0; j < 4; ++j, v <<= 2)
- *destP++ = _indexes[v >> 6];
+ *destP++ = EGA_INDEXES[_indexes[v >> 6]];
}
return true;
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
index 25ce9b1227c..bff229056dd 100644
--- a/engines/mm/mm1/gfx/screen_decoder.h
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -33,7 +33,7 @@ class ScreenDecoder : public Image::ImageDecoder {
private:
Graphics::Surface _surface;
public:
- byte _indexes[4] = { 0 }; // Palete indexes used
+ byte _indexes[4] = { 0 }; // EGA palete indexes used
public:
ScreenDecoder() {}
~ScreenDecoder() override;
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index ea88afe484f..b11417f3b87 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -29,7 +29,6 @@
#include "mm/mm1/mm1.h"
#include "mm/mm1/console.h"
#include "mm/mm1/gfx/gfx.h"
-//#include "mm/xeen/files.h"
#include "mm/mm1/views/game.h"
#include "mm/mm1/views_enh/game.h"
@@ -106,6 +105,7 @@ bool MM1Engine::setupEnhanced() {
for (int i = 0; i < PALETTE_SIZE; ++i)
pal[i] = f.readByte() << 2;
g_system->getPaletteManager()->setPalette(pal, 0, PALETTE_COUNT);
+ Gfx::GFX::findPalette(pal);
// Show the mouse cursor
g_events->loadCursors();
Commit: 40743e9a86089b73d934fa956bc4f9bdf2e2e7a4
https://github.com/scummvm/scummvm/commit/40743e9a86089b73d934fa956bc4f9bdf2e2e7a4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Go to Are You Ready screen from title screen
Changed paths:
engines/mm/mm1/views/title.cpp
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index 48ca517337a..08e1ed1bc15 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -132,7 +132,7 @@ void Title::timeout() {
bool Title::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
// Show the main menu
- g_events->replaceView("MainMenu");
+ g_events->replaceView("AreYouReady");
} else if (msg.keycode == Common::KEYCODE_SPACE) {
// Start showing game screens slideshow
Commit: 03f3adde3fb4e9a1d8ee091ddea90c161585a5f6
https://github.com/scummvm/scummvm/commit/03f3adde3fb4e9a1d8ee091ddea90c161585a5f6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:41+01:00
Commit Message:
MM: MM1: Start implementing proper per-map colors.
Basically, I've given up. For a while I thought I'd located
where the color offsets were stored, in an array of 18
that maps can individually choose from. However, I just
couldn't get the values to work to display colors correctly.
I'm severely hampered by the damn bitplanes the EGA had,
making the MM1 disassembly impossible to understand.
Even worse, I'm not entirely sure whether the game is even
using the default EGA palette or not. So, I've given up on
using the original data array, and am going to manually figure
out the colors the maps are using, and construct my own
colors array to properly specify the EGA palette indexes
Changed paths:
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 462f4b919c0..138f4b4c0fe 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -119,6 +119,10 @@ static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
128, 96, 64, 32, 128, 96, 64, 32, 96, 64, 32, 16
};
+static byte TILE_COLORS[18] = {
+ 0xe6, 0xe6, 0xe6, 0x72, 0x72, 0x72, 0x62, 0x62, 0x62,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
Maps::Maps() {
g_maps = this;
@@ -368,9 +372,11 @@ void Maps::loadTile() {
tiles.resize(RESOURCE_TILES_COUNT);
Gfx::ScreenDecoder decoder;
+ byte colors = TILE_COLORS[entryIndex];
+ assert(colors);
decoder._indexes[0] = 0;
- decoder._indexes[1] = 6;
- decoder._indexes[2] = 14;
+ decoder._indexes[1] = colors & 0xf;
+ decoder._indexes[2] = (colors >> 4) & 0xf;
decoder._indexes[3] = 15;
for (int i = 0; i < RESOURCE_TILES_COUNT; ++i) {
Commit: 9b537e0b2ffc8e8a4b1f64b08fb040498750f2fe
https://github.com/scummvm/scummvm/commit/9b537e0b2ffc8e8a4b1f64b08fb040498750f2fe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Fix ladder string in map 11
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map11.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 398c3777ca2..cac51482f6c 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1148,6 +1148,7 @@ maps:
tip2: "THIS CAVERN IS RANDOM UNTIL THE DIALS\nARE SET."
dial: "STABILIZATION DIAL #%c SET (A-Z)?"
poof: "POOF! YOU'VE BEEN TELEPORTED..."
+ ladder: "A LADDER GOING UP, TAKE IT (Y/N)?"
map12:
polyhedron1: "ATOP A CRYSTAL PYRAMID SPINS A GLOWING\nPOLYHEDRON. STOP IT ON SIDE (1-9)?"
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 011bffc5037..100bedc4ea4 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -68,7 +68,7 @@ void Map11::special() {
void Map11::special00() {
send(SoundMessage(
- STRING["maps.ladder_up"],
+ STRING["maps.map11.ladder"],
[]() {
g_maps->_mapPos = Common::Point(7, 2);
g_maps->changeMap(0xf04, 2);
Commit: 08a3d4683425bb6edb6f39aa4638fefcce07b967
https://github.com/scummvm/scummvm/commit/08a3d4683425bb6edb6f39aa4638fefcce07b967
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Fix first view when loading a town on startup
Changed paths:
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 138f4b4c0fe..c53211268d3 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -231,6 +231,7 @@ void Maps::select(uint16 id, byte section) {
_id = id;
_section = section;
+
uint mapId = getIndex(id, section);
load(mapId);
}
@@ -238,7 +239,7 @@ void Maps::select(uint16 id, byte section) {
void Maps::display(uint16 id, byte section) {
select(id, section);
loadTiles();
- g_events->send("Game", GameMessage("DISPLAY"));
+ g_events->send("Game", GameMessage("UPDATE"));
}
void Maps::loadTown(TownId townId) {
Commit: 88bcf16d32ef1922d251bbd87261e31c28030e9a
https://github.com/scummvm/scummvm/commit/88bcf16d32ef1922d251bbd87261e31c28030e9a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Fix dead display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/dead.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index cac51482f6c..02a523ba433 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1,4 +1,4 @@
- dialogs:
+dialogs:
location:
titles:
0: "--TRAINING--"
diff --git a/engines/mm/mm1/views/dead.cpp b/engines/mm/mm1/views/dead.cpp
index bc031a4627d..40d97f31da3 100644
--- a/engines/mm/mm1/views/dead.cpp
+++ b/engines/mm/mm1/views/dead.cpp
@@ -41,7 +41,7 @@ bool Dead::msgFocus(const FocusMessage &msg) {
void Dead::draw() {
clearSurface();
writeLine(4);
- writeString(6, 10, STRING["dialogs.dead.1"]);
+ writeString(11, 6, STRING["dialogs.dead.1"]);
writeString(7, 8, STRING["dialogs.dead.2"]);
writeString(7, 10, STRING["dialogs.dead.3"]);
writeString(8, 12, STRING["dialogs.dead.4"]);
Commit: 4d9300ebbf99f49910134e54d6ce5f45b041014e
https://github.com/scummvm/scummvm/commit/4d9300ebbf99f49910134e54d6ce5f45b041014e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Fix display of blacksmith buy subviews
Changed paths:
engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
engines/mm/mm1/views/locations/blacksmith_subview.cpp
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
index 53ec01ca6ad..b0e89c8ef83 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_armor.cpp
@@ -47,7 +47,7 @@ bool BlacksmithBuyArmor::msgFocus(const FocusMessage &msg) {
void BlacksmithBuyArmor::draw() {
Location::draw();
- writeString(23, 1, STRING["dialogs.blacksmith.armor"]);
+ writeString(23, 0, STRING["dialogs.blacksmith.armor"]);
drawItems();
}
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
index 3f05165c22c..c6832939595 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_misc.cpp
@@ -47,7 +47,7 @@ bool BlacksmithBuyMisc::msgFocus(const FocusMessage &msg) {
void BlacksmithBuyMisc::draw() {
Location::draw();
- writeString(23, 1, STRING["dialogs.blacksmith.misc"]);
+ writeString(23, 0, STRING["dialogs.blacksmith.misc"]);
drawItems();
}
diff --git a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
index 9baea69d525..f77a4a45aeb 100644
--- a/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_buy_weapons.cpp
@@ -47,7 +47,7 @@ bool BlacksmithBuyWeapons::msgFocus(const FocusMessage &msg) {
void BlacksmithBuyWeapons::draw() {
Location::draw();
- writeString(23, 1, STRING["dialogs.blacksmith.weapons"]);
+ writeString(23, 0, STRING["dialogs.blacksmith.weapons"]);
drawItems();
}
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index b6cec655900..2c0d02fed33 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -38,7 +38,7 @@ BlacksmithSellItem::BlacksmithSellItem() :
void BlacksmithSellItem::draw() {
Location::draw();
- writeString(22, 1, STRING["dialogs.blacksmith.backpack"]);
+ writeString(22, 0, STRING["dialogs.blacksmith.backpack"]);
drawItems();
}
diff --git a/engines/mm/mm1/views/locations/blacksmith_subview.cpp b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
index c3f12dcc01d..6cc951bf58b 100644
--- a/engines/mm/mm1/views/locations/blacksmith_subview.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
@@ -32,7 +32,7 @@ namespace Locations {
void BlacksmithSubview::drawItems() {
for (int idx = 0; idx < INVENTORY_COUNT; ++idx) {
- writeChar(17, 1, 'A' + idx);
+ writeChar(17, 1 + idx, 'A' + idx);
writeString(") ");
g_globals->_items.getItem(_items[idx]);
Commit: 213632a62dd528a263e50e8ee9cbd71a61fc672a
https://github.com/scummvm/scummvm/commit/213632a62dd528a263e50e8ee9cbd71a61fc672a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Fix display of staff in blacksmith buy weapons
Changed paths:
devtools/create_mm/files/mm1/items.txt
engines/mm/mm1/data/items.cpp
diff --git a/devtools/create_mm/files/mm1/items.txt b/devtools/create_mm/files/mm1/items.txt
index 674f6412be7..a3ad1aa44bc 100644
--- a/devtools/create_mm/files/mm1/items.txt
+++ b/devtools/create_mm/files/mm1/items.txt
@@ -83,7 +83,6 @@
"ROBBER'S X-BOW", 62, 29, 4, 255, 61, 10, 8000, 10, 5
"ARCHER'S BOW ", 55, 31, 5, 255, 85, 10, 12000, 20, 5
"OBSIDIAN BOW ", 0, 255, 0, 255, 80, 3, 2000, 3, 0
-" ", 0, 0, 0, 0, 0, 0, 0, 0, 0
"STAFF ", 1, 0, 0, 0, 0, 0, 30, 8, 0
"GLAIVE ", 7, 0, 0, 0, 0, 0, 80, 10, 0
"BARDICHE ", 7, 0, 0, 0, 0, 0, 80, 10, 0
diff --git a/engines/mm/mm1/data/items.cpp b/engines/mm/mm1/data/items.cpp
index bdd50db3991..4328194a515 100644
--- a/engines/mm/mm1/data/items.cpp
+++ b/engines/mm/mm1/data/items.cpp
@@ -30,8 +30,8 @@ bool ItemsArray::load() {
if (!f.open("items.txt"))
return false;
- resize(256);
- for (int lineNum = 0; lineNum < 256; ++lineNum) {
+ resize(255);
+ for (int lineNum = 0; lineNum < 255; ++lineNum) {
Item &item = (*this)[lineNum];
Common::String line = f.readLine();
assert(line.size() > 20 && line[0] == '"' && line[15] == '"');
@@ -54,7 +54,8 @@ bool ItemsArray::load() {
}
Item *ItemsArray::getItem(byte index) const {
- g_globals->_currItem = (*this)[index];
+ assert(index > 0);
+ g_globals->_currItem = (*this)[index - 1];
g_globals->_currItem._name = STRING[Common::String::format(
"stats.items.%d", (int)index)];
Commit: 508a478fa3d1aa14f3fa2717084a6b0b5842030d
https://github.com/scummvm/scummvm/commit/508a478fa3d1aa14f3fa2717084a6b0b5842030d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Finish blacksmith selling item code
Changed paths:
engines/mm/mm1/data/items.cpp
engines/mm/mm1/data/items.h
engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
engines/mm/mm1/views/locations/blacksmith_subview.cpp
diff --git a/engines/mm/mm1/data/items.cpp b/engines/mm/mm1/data/items.cpp
index 4328194a515..ca52aff236c 100644
--- a/engines/mm/mm1/data/items.cpp
+++ b/engines/mm/mm1/data/items.cpp
@@ -25,6 +25,15 @@
namespace MM {
namespace MM1 {
+uint Item::getSellCost() const {
+ uint cost = _cost;
+ if (_maxCharges)
+ cost /= 2;
+ cost /= 2;
+
+ return cost;
+}
+
bool ItemsArray::load() {
Common::File f;
if (!f.open("items.txt"))
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 08a79cc56d5..b3aeb0c67e9 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -95,6 +95,11 @@ struct ItemData {
struct Item : public ItemData {
Common::String _name;
+
+ /**
+ * Get the sell value
+ */
+ uint getSellCost() const;
};
struct ItemsArray : public Common::Array<Item>, public TextParser {
diff --git a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
index 2c0d02fed33..5cefc659425 100644
--- a/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_sell_item.cpp
@@ -43,37 +43,29 @@ void BlacksmithSellItem::draw() {
}
void BlacksmithSellItem::drawItems() {
- // TODO: List items to sell
- for (int idx = 0; idx < INVENTORY_COUNT; ++idx) {
+ const Inventory &inv = g_globals->_currCharacter->_backpack;
+ for (uint idx = 0; idx < INVENTORY_COUNT; ++idx) {
+ writeChar(17, 1 + idx, 'A' + idx);
+ writeString(") ");
+
+ if (idx < inv.size()) {
+ g_globals->_items.getItem(inv[idx]._id);
+ writeString(g_globals->_currItem._name);
+ _textPos.x = 35;
+ writeNumber(g_globals->_currItem.getSellCost());
+ }
}
}
void BlacksmithSellItem::selectItem(uint index) {
Character &c = *g_globals->_currCharacter;
- int itemIndex = index;
-
- // Some slots may be empty, so we need to iterate
- // until we found the index'ed filled in slot
- for (index = 0; index < INVENTORY_COUNT ; ++index) {
- if (c._backpack[index]) {
- if (--itemIndex == 0)
- break;
- }
- }
- if (index == INVENTORY_COUNT)
- return;
-
- // Remove the item
- int itemId = c._backpack[index]._id;
- int v14 = c._backpack[index]._charges;
- c._backpack.removeAt(index);
-
- g_globals->_items.getItem(itemId);
- if (!v14 && g_globals->_currItem._maxCharges)
- g_globals->_currItem._cost /= 2;
+ Inventory &inv = c._backpack;
+ assert(index < inv.size());
+ g_globals->_items.getItem(inv[index]._id);
- c._gold += g_globals->_currItem._cost / 2;
+ c._gold += g_globals->_currItem.getSellCost();
+ inv.removeAt(index);
}
} // namespace Locations
diff --git a/engines/mm/mm1/views/locations/blacksmith_subview.cpp b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
index 6cc951bf58b..ec6869900ee 100644
--- a/engines/mm/mm1/views/locations/blacksmith_subview.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
@@ -68,6 +68,7 @@ bool BlacksmithSubview::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_e:
case Common::KEYCODE_f:
selectItem(msg.keycode - Common::KEYCODE_a);
+ draw();
break;
default:
break;
Commit: 0893f3a2a5fbbd10c1271d339c169136e86d65c5
https://github.com/scummvm/scummvm/commit/0893f3a2a5fbbd10c1271d339c169136e86d65c5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Fix character info view for sorcerers
Changed paths:
engines/mm/mm1/views/character_base.cpp
diff --git a/engines/mm/mm1/views/character_base.cpp b/engines/mm/mm1/views/character_base.cpp
index a56712d1ada..00df3e5e01c 100644
--- a/engines/mm/mm1/views/character_base.cpp
+++ b/engines/mm/mm1/views/character_base.cpp
@@ -31,8 +31,7 @@ void CharacterBase::printStats() {
Character &re = *g_globals->_currCharacter;
printSummary();
- newLine();
- writeString(STRING["stats.attributes.int"]);
+ writeString(0, 2, STRING["stats.attributes.int"]);
writeNumber(re._intelligence);
_textPos.x = 8;
writeString(STRING["stats.attributes.level"]);
Commit: 6958216708b6b86b04effb6da6a1bdfa7f4aab1a
https://github.com/scummvm/scummvm/commit/6958216708b6b86b04effb6da6a1bdfa7f4aab1a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:42+01:00
Commit Message:
MM: MM1: Add enhanced minimap colors for exits and businesses
Changed paths:
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map06.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map13.cpp
engines/mm/mm1/maps/map14.cpp
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/maps/map19.cpp
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/maps/map28.cpp
engines/mm/mm1/maps/map29.cpp
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/map32.cpp
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/map34.cpp
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map38.cpp
engines/mm/mm1/maps/map39.cpp
engines/mm/mm1/maps/map40.cpp
engines/mm/mm1/maps/map41.cpp
engines/mm/mm1/maps/map42.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map44.cpp
engines/mm/mm1/maps/map45.cpp
engines/mm/mm1/maps/map46.cpp
engines/mm/mm1/maps/map47.cpp
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map50.cpp
engines/mm/mm1/maps/map51.cpp
engines/mm/mm1/maps/map52.cpp
engines/mm/mm1/maps/map53.cpp
engines/mm/mm1/maps/map_town.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views_enh/map.cpp
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index c87cebb7243..afb6969b5c0 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -58,6 +58,7 @@ darkness:
// Encounter checks
g_globals->_encounters._encounterType = NORMAL_SURPRISED;
if (maps._currentState & Maps::CELL_SPECIAL) {
+ map.visitedSpecial();
map.special();
} else if (_stepRandom) {
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 2aac83bfe04..b0696c376ff 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -122,6 +122,19 @@ void Map::unlockDoor() {
g_maps->_forwardMask & 0x55;
}
+void Map::visitedSpecial() {
+ if (!_visited[g_maps->_mapOffset])
+ _visited[g_maps->_mapOffset] = VISITED_SPECIAL;
+}
+
+void Map::visitedExit() {
+ _visited[g_maps->_mapOffset] = VISITED_EXIT;
+}
+
+void Map::visitedBusiness() {
+ _visited[g_maps->_mapOffset] = VISITED_BUSINESS;
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 161de883b50..b1f3eb08b7b 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -206,6 +206,21 @@ public:
* Unlocks door
*/
void unlockDoor();
+
+ /**
+ * Visited a special cell
+ */
+ void visitedSpecial();
+
+ /**
+ * Visited an exit cell
+ */
+ void visitedExit();
+
+ /**
+ * Visited a business cell
+ */
+ void visitedBusiness();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index a6f2685ed66..efb9b82b7c9 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -92,6 +92,7 @@ void Map00::special03() {
}
void Map00::special04() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map00.passage_outside"],
[]() {
@@ -164,6 +165,7 @@ void Map00::special08() {
}
void Map00::special09() {
+ visitedExit();
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
@@ -255,6 +257,7 @@ void Map00::special22() {
}
void Map00::special23() {
+ visitedExit();
Common::String msg = STRING["maps.map00.trapdoor"];
if (g_globals->_activeSpells._s.levitate)
msg += STRING["maps.map00.levitate"];
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index ab106174558..fe7cd528310 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -86,6 +86,7 @@ void Map01::special03() {
}
void Map01::special04() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map01.passage_outside"],
[]() {
@@ -138,6 +139,7 @@ void Map01::special08() {
}
void Map01::special09() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map01.passage_outside"],
[]() {
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 850c24bea5f..74d2bb36319 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -93,6 +93,7 @@ void Map02::special03() {
}
void Map02::special04() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map02.passage_outside"],
[]() {
@@ -149,6 +150,7 @@ void Map02::special14() {
}
void Map02::special15() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map02.portal"],
[]() {
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 82f3caa91f4..071e9c5c6fa 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -124,6 +124,7 @@ void Map03::special03() {
}
void Map03::special04() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map01.passage_outside"],
[]() {
@@ -153,6 +154,7 @@ void Map03::special08() {
}
void Map03::special09() {
+ visitedExit();
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 5ac7a7b2d92..13583c0a236 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -110,6 +110,7 @@ void Map04::special03() {
}
void Map04::special04() {
+ visitedExit();
if (_data[MAP04_PASSAGE_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
send(SoundMessage(
STRING["maps.map04.passage_outside"],
@@ -147,6 +148,7 @@ void Map04::special08() {
}
void Map04::special09() {
+ visitedExit();
if (_data[MAP04_STAIRS_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
if (_data[MAP04_STAIRS_OVERRIDE] < 255)
_data[MAP04_STAIRS_OVERRIDE]++;
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 46b15eda351..7a8fed5c4ca 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -54,6 +54,7 @@ void Map05::special() {
}
void Map05::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
@@ -106,6 +107,7 @@ void Map05::special06() {
}
void Map05::special07() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map05.portal"],
[]() {
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
index 20fc20df081..9af6fab92c0 100644
--- a/engines/mm/mm1/maps/map06.cpp
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -91,6 +91,7 @@ void Map06::special() {
}
void Map06::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map06.passage_outside"],
[]() {
@@ -101,6 +102,7 @@ void Map06::special00() {
}
void Map06::special01() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map06.portal"],
[]() {
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index c732df44137..e1ff7c66f97 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -57,6 +57,7 @@ void Map07::special() {
}
void Map07::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
@@ -67,6 +68,7 @@ void Map07::special00() {
}
void Map07::special01() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map07.portal"],
[]() {
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index c35681c22f2..ff263e2144a 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -56,6 +56,7 @@ void Map08::special() {
}
void Map08::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
@@ -66,6 +67,7 @@ void Map08::special00() {
}
void Map08::special01() {
+ visitedExit();
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index 4dfa8a32c80..1153bc1008c 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -54,6 +54,7 @@ void Map09::special() {
}
void Map09::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
@@ -63,6 +64,7 @@ void Map09::special00() {
}
void Map09::special01() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map09.passage_outside"],
[]() {
@@ -211,6 +213,7 @@ void Map09::special27() {
}
void Map09::portal(int index) {
+ visitedExit();
_portalIndex = index;
send(SoundMessage(
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index 37ff30060a6..ab82fd0d4ac 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -65,6 +65,7 @@ void Map10::special() {
}
void Map10::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map10.passage_outside"],
[]() {
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 100bedc4ea4..059ced16619 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -67,6 +67,7 @@ void Map11::special() {
}
void Map11::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map11.ladder"],
[]() {
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index 91843696bba..18d26a707f8 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -54,6 +54,7 @@ void Map12::special() {
}
void Map12::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.ladder_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map13.cpp b/engines/mm/mm1/maps/map13.cpp
index 69103b57f32..f012757b2db 100644
--- a/engines/mm/mm1/maps/map13.cpp
+++ b/engines/mm/mm1/maps/map13.cpp
@@ -75,6 +75,7 @@ void Map13::special() {
}
void Map13::special00() {
+ visitedExit();
_data[VAL1] = 0;
send(SoundMessage(
STRING["maps.map13.passage_outside"],
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
index 5974fcf55d4..26ba95c944d 100644
--- a/engines/mm/mm1/maps/map14.cpp
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -145,6 +145,7 @@ void Map14::special03() {
}
void Map14::special04() {
+ visitedExit();
if (_data[VAL2]) {
send(SoundMessage(
STRING["maps.map14.passage"],
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index fa4330f5bc9..25188fedd96 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -53,6 +53,7 @@ void Map18::special() {
}
void Map18::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map18.passage"],
[]() {
@@ -63,6 +64,7 @@ void Map18::special00() {
}
void Map18::special01() {
+ visitedExit();
if (_data[VAL1] & 0x80) {
g_maps->_mapPos = Common::Point(0, 7);
g_maps->changeMap(0x508, 3);
@@ -89,6 +91,7 @@ void Map18::special01() {
}
void Map18::special02() {
+ visitedExit();
if (_data[VAL2] & 0x80) {
g_maps->_mapPos = Common::Point(7, 15);
g_maps->changeMap(0xf08, 3);
@@ -115,6 +118,7 @@ void Map18::special02() {
}
void Map18::special03() {
+ visitedExit();
send(SoundMessage(STRING["maps.map18.ruins"],
[]() {
g_maps->_mapPos = Common::Point(2, 2);
@@ -152,6 +156,7 @@ void Map18::special07() {
}
void Map18::special08() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map18.cave"],
[]() {
diff --git a/engines/mm/mm1/maps/map19.cpp b/engines/mm/mm1/maps/map19.cpp
index c6ed7c8fb55..84fcac22356 100644
--- a/engines/mm/mm1/maps/map19.cpp
+++ b/engines/mm/mm1/maps/map19.cpp
@@ -62,6 +62,7 @@ void Map19::special00() {
}
void Map19::special01() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map19.cave"],
[]() {
@@ -72,6 +73,7 @@ void Map19::special01() {
}
void Map19::special02() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map19.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index 827f41e91f0..c17a281c4a2 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -70,6 +70,7 @@ void Map20::special() {
}
void Map20::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map20.stairs_down"],
[]() {
@@ -80,6 +81,7 @@ void Map20::special00() {
}
void Map20::special01() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map20.cave"],
[]() {
@@ -90,6 +92,7 @@ void Map20::special01() {
}
void Map20::special02() {
+ visitedExit();
if (_data[VAL1] & 0x80) {
g_maps->_mapPos = Common::Point(15, 8);
g_maps->changeMap(0xa11, 3);
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index 7d63f667098..f9604fbd405 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -59,6 +59,7 @@ void Map23::special() {
}
void Map23::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map23.passage"],
[]() {
@@ -69,6 +70,7 @@ void Map23::special00() {
}
void Map23::special01() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map23.cave"],
[]() {
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index 78d54eb482c..fbff4b37643 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -141,6 +141,7 @@ void Map25::special() {
}
void Map25::special00() {
+ visitedExit();
send(SoundMessage(
STRING["maps.map25.portal"],
[]() {
@@ -151,17 +152,16 @@ void Map25::special00() {
}
void Map25::special01() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- if (c.hasItem(CORAL_KEY_ID)) {
- send(InfoMessage(
- STRING["maps.map25.key"],
- []() {
- g_maps->_mapPos = Common::Point(7, 5);
- g_maps->changeMap(0x212, 1);
- }
- ));
- }
+ visitedExit();
+
+ if (g_globals->_party.hasItem(CORAL_KEY_ID)) {
+ send(InfoMessage(
+ STRING["maps.map25.key"],
+ []() {
+ g_maps->_mapPos = Common::Point(7, 5);
+ g_maps->changeMap(0x212, 1);
+ }
+ ));
}
}
diff --git a/engines/mm/mm1/maps/map28.cpp b/engines/mm/mm1/maps/map28.cpp
index 30395878e90..9652be5000d 100644
--- a/engines/mm/mm1/maps/map28.cpp
+++ b/engines/mm/mm1/maps/map28.cpp
@@ -174,6 +174,8 @@ void Map28::special00() {
}
void Map28::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map28.cave"],
[]() {
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
index 85c0459c67e..a45b3e56ef3 100644
--- a/engines/mm/mm1/maps/map29.cpp
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -83,6 +83,8 @@ void Map29::special() {
}
void Map29::special00() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map29.algary"],
[]() {
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index c8cd6218d14..ee97a1c8caa 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -70,6 +70,8 @@ void Map30::special() {
}
void Map30::special00() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map30.passage"],
[]() {
@@ -80,6 +82,8 @@ void Map30::special00() {
}
void Map30::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map30.ruins"],
[]() {
diff --git a/engines/mm/mm1/maps/map32.cpp b/engines/mm/mm1/maps/map32.cpp
index e80021f1eca..db5ab4aec07 100644
--- a/engines/mm/mm1/maps/map32.cpp
+++ b/engines/mm/mm1/maps/map32.cpp
@@ -57,6 +57,8 @@ void Map32::special() {
}
void Map32::special00() {
+ visitedExit();
+
if (!g_globals->_party.hasItem(DIAMOND_KEY_ID)) {
send(SoundMessage(STRING["maps.map32.door"]));
} else {
@@ -76,6 +78,8 @@ void Map32::special01() {
}
void Map32::special02() {
+ visitedExit();
+
if (_data[VAL2] & 0x80) {
g_maps->_mapPos = Common::Point(0, 7);
g_maps->changeMap(0xb07, 3);
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index 77a480b4d6b..bd51ff86e1c 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -146,6 +146,8 @@ void Map33::special00() {
}
void Map33::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map33.building"],
[]() {
diff --git a/engines/mm/mm1/maps/map34.cpp b/engines/mm/mm1/maps/map34.cpp
index e3422d8e123..b9e90d28110 100644
--- a/engines/mm/mm1/maps/map34.cpp
+++ b/engines/mm/mm1/maps/map34.cpp
@@ -56,6 +56,8 @@ void Map34::special00() {
}
void Map34::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map34.passage"],
[]() {
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 1e9b2908904..91c005d67a0 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -68,6 +68,8 @@ void Map35::special00() {
}
void Map35::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map35.exit"],
[]() {
@@ -78,6 +80,8 @@ void Map35::special01() {
}
void Map35::special02() {
+ visitedExit();
+
send(SoundMessage(STRING["maps.map35.slide"]));
g_maps->_mapPos = Common::Point(14, 9);
g_maps->changeMap(0xa00, 2);
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index 4f7e232f42b..e388afd094f 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -65,6 +65,8 @@ void Map36::special00() {
}
void Map36::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map36.exit"],
[]() {
@@ -75,6 +77,8 @@ void Map36::special01() {
}
void Map36::special02() {
+ visitedExit();
+
send(SoundMessage(STRING["maps.map36.slide"]));
g_maps->_mapPos = Common::Point(12, 2);
g_maps->changeMap(0xa00, 2);
@@ -99,6 +103,8 @@ void Map36::special05() {
}
void Map36::special06() {
+ visitedExit();
+
send(SoundMessage(STRING["maps.map36.pit"]));
g_maps->_mapPos = Common::Point(7, 4);
g_maps->changeMap(0x705, 3);
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index 4fc01d4e3e4..9d088725619 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -62,6 +62,8 @@ void Map37::special01() {
if (_data[VAL1]) {
none160();
} else {
+ visitedExit();
+
for (uint i = 0; i < g_globals->_party.size(); ++i) {
g_globals->_party[i]._flags[5] |= CHARFLAG5_1;
}
@@ -77,6 +79,8 @@ void Map37::special01() {
}
void Map37::special02() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map38.cpp b/engines/mm/mm1/maps/map38.cpp
index dc66b2b0599..38ad7244a11 100644
--- a/engines/mm/mm1/maps/map38.cpp
+++ b/engines/mm/mm1/maps/map38.cpp
@@ -63,6 +63,8 @@ void Map38::special02() {
}
void Map38::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map39.cpp b/engines/mm/mm1/maps/map39.cpp
index 4b5a56856a9..2e3b2dc3aa4 100644
--- a/engines/mm/mm1/maps/map39.cpp
+++ b/engines/mm/mm1/maps/map39.cpp
@@ -55,6 +55,8 @@ void Map39::special00() {
}
void Map39::special01() {
+ visitedExit();
+
for (uint i = 0; i < g_globals->_party.size(); ++i) {
g_globals->_party[i]._flags[7] |= CHARFLAG7_1;
}
@@ -69,6 +71,8 @@ void Map39::special01() {
}
void Map39::special02() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map40.cpp b/engines/mm/mm1/maps/map40.cpp
index 55a1ae795e7..edb6df12ca1 100644
--- a/engines/mm/mm1/maps/map40.cpp
+++ b/engines/mm/mm1/maps/map40.cpp
@@ -79,6 +79,8 @@ void Map40::special02() {
}
void Map40::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map41.cpp b/engines/mm/mm1/maps/map41.cpp
index 7269e929e72..438aa451e70 100644
--- a/engines/mm/mm1/maps/map41.cpp
+++ b/engines/mm/mm1/maps/map41.cpp
@@ -52,6 +52,8 @@ void Map41::special00() {
}
void Map41::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.maps40.stairs_up"],
[]() {
@@ -62,6 +64,8 @@ void Map41::special01() {
}
void Map41::special02() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
index 20a07cb5c59..442e6f6edb7 100644
--- a/engines/mm/mm1/maps/map42.cpp
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -136,6 +136,8 @@ void Map42::special14() {
}
void Map42::special15() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 129e633a009..4a7449be47b 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -68,6 +68,8 @@ void Map43::special00() {
void Map43::special01() {
_data[VAL1] = 0;
if (g_maps->_forwardMask == DIRMASK_E) {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map43.exit"],
[]() {
diff --git a/engines/mm/mm1/maps/map44.cpp b/engines/mm/mm1/maps/map44.cpp
index 6545e9af604..4cc4472eda1 100644
--- a/engines/mm/mm1/maps/map44.cpp
+++ b/engines/mm/mm1/maps/map44.cpp
@@ -54,6 +54,8 @@ void Map44::special00() {
}
void Map44::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map44.exit"],
[]() {
@@ -64,6 +66,8 @@ void Map44::special01() {
}
void Map44::special02() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map45.cpp b/engines/mm/mm1/maps/map45.cpp
index 1ea735b76a4..5a3ab9443bb 100644
--- a/engines/mm/mm1/maps/map45.cpp
+++ b/engines/mm/mm1/maps/map45.cpp
@@ -54,6 +54,8 @@ void Map45::special00() {
}
void Map45::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map45.passage"],
[]() {
@@ -68,6 +70,8 @@ void Map45::special02() {
}
void Map45::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
@@ -77,6 +81,8 @@ void Map45::special03() {
}
void Map45::special04() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map46.cpp b/engines/mm/mm1/maps/map46.cpp
index 72ea64573b9..ce78e564094 100644
--- a/engines/mm/mm1/maps/map46.cpp
+++ b/engines/mm/mm1/maps/map46.cpp
@@ -58,6 +58,8 @@ void Map46::special01() {
}
void Map46::special02() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
@@ -67,6 +69,8 @@ void Map46::special02() {
}
void Map46::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map47.cpp b/engines/mm/mm1/maps/map47.cpp
index 31afeebf87b..8610cbb5ea5 100644
--- a/engines/mm/mm1/maps/map47.cpp
+++ b/engines/mm/mm1/maps/map47.cpp
@@ -88,6 +88,8 @@ void Map47::special02() {
}
void Map47::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index bc9c51fa1f7..7797ecbd089 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -57,6 +57,8 @@ void Map49::special00() {
}
void Map49::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map49.passage"],
[]() {
@@ -67,6 +69,8 @@ void Map49::special01() {
}
void Map49::special02() {
+ visitedExit();
+
g_maps->_mapPos = Common::Point(15, 7);
g_maps->changeMap(0xb1a, 2);
send(SoundMessage(STRING["maps.map49.chute"]));
@@ -112,6 +116,8 @@ void Map49::special06() {
}
void Map49::special07() {
+ visitedExit();
+
reduceHP();
reduceHP();
g_maps->_mapPos = Common::Point(4, 7);
diff --git a/engines/mm/mm1/maps/map50.cpp b/engines/mm/mm1/maps/map50.cpp
index bc0de523b31..5fd9091b876 100644
--- a/engines/mm/mm1/maps/map50.cpp
+++ b/engines/mm/mm1/maps/map50.cpp
@@ -54,6 +54,8 @@ void Map50::special00() {
}
void Map50::special01() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map50.passage"],
[]() {
@@ -64,6 +66,8 @@ void Map50::special01() {
}
void Map50::special02() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
@@ -73,6 +77,8 @@ void Map50::special02() {
}
void Map50::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
@@ -82,6 +88,8 @@ void Map50::special03() {
}
void Map50::special04() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
diff --git a/engines/mm/mm1/maps/map51.cpp b/engines/mm/mm1/maps/map51.cpp
index 6df15f9265b..8a020f91bd3 100644
--- a/engines/mm/mm1/maps/map51.cpp
+++ b/engines/mm/mm1/maps/map51.cpp
@@ -63,6 +63,8 @@ void Map51::special01() {
}
void Map51::special02() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
@@ -72,6 +74,8 @@ void Map51::special02() {
}
void Map51::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map52.cpp b/engines/mm/mm1/maps/map52.cpp
index 14afbadaa83..aff073b9f1d 100644
--- a/engines/mm/mm1/maps/map52.cpp
+++ b/engines/mm/mm1/maps/map52.cpp
@@ -62,6 +62,8 @@ void Map52::special01() {
}
void Map52::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
@@ -71,6 +73,8 @@ void Map52::special03() {
}
void Map52::special04() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map53.cpp b/engines/mm/mm1/maps/map53.cpp
index c6bef03b414..aa6d5a2eab2 100644
--- a/engines/mm/mm1/maps/map53.cpp
+++ b/engines/mm/mm1/maps/map53.cpp
@@ -64,6 +64,8 @@ void Map53::special01() {
}
void Map53::special03() {
+ visitedExit();
+
send(SoundMessage(
STRING["maps.map53.ladder_up"],
[]() {
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
index c6f572e6093..76771505638 100644
--- a/engines/mm/mm1/maps/map_town.cpp
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -30,6 +30,8 @@ namespace MM1 {
namespace Maps {
void MapTown::blacksmith() {
+ visitedBusiness();
+
send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.blacksmith_inside", _mapIndex)],
[]() {
@@ -39,6 +41,8 @@ void MapTown::blacksmith() {
}
void MapTown::inn() {
+ visitedBusiness();
+
send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.inn_inside", _mapIndex)],
[]() {
@@ -48,6 +52,8 @@ void MapTown::inn() {
}
void MapTown::market() {
+ visitedBusiness();
+
send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.market_inside", _mapIndex)],
[]() {
@@ -57,6 +63,8 @@ void MapTown::market() {
}
void MapTown::tavern() {
+ visitedBusiness();
+
send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.tavern_inside", _mapIndex)],
[]() {
@@ -66,6 +74,8 @@ void MapTown::tavern() {
}
void MapTown::temple() {
+ visitedBusiness();
+
send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.temple_inside", _mapIndex)],
[]() {
@@ -75,6 +85,8 @@ void MapTown::temple() {
}
void MapTown::training() {
+ visitedBusiness();
+
send(SoundMessage(
STRING[Common::String::format("maps.map%.2u.training_inside", _mapIndex)],
[]() {
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index c53211268d3..18ca6c0f4d4 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -277,7 +277,9 @@ void Maps::loadTown(TownId townId) {
break;
}
- _currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x] = true;
+ byte &visited = _currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x];
+ if (!visited)
+ visited = VISITED_NORMAL;
}
void Maps::town15setup() {
@@ -426,7 +428,9 @@ void Maps::turnAround() {
void Maps::step(const Common::Point &delta) {
_mapPos += delta;
- _currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x] = true;
+ byte &visited = _currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x];
+ if (!visited)
+ visited = VISITED_NORMAL;
int section = 0, id = 0;
if (_mapPos.x < 0) {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 23755d7015b..24666340b0f 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -45,6 +45,11 @@ enum StateFlag {
SFLAG_DISABLE_MONSTER_SPELLS = 2
};
+enum Visited {
+ VISITED_NONE = 0, VISITED_NORMAL = 1, VISITED_SPECIAL = 2,
+ VISITED_EXIT = 3, VISITED_BUSINESS = 4
+};
+
/**
* Container for all the game maps
*/
diff --git a/engines/mm/mm1/views_enh/map.cpp b/engines/mm/mm1/views_enh/map.cpp
index f7475b32bc1..258ba15130f 100644
--- a/engines/mm/mm1/views_enh/map.cpp
+++ b/engines/mm/mm1/views_enh/map.cpp
@@ -59,9 +59,9 @@ void Map::draw() {
mazeY >= yStart; yp += TILE_H, --mazeY) {
for (int xp = BORDER_SIZE, mazeX = xStart;
mazeX < (xStart + totalX); xp += TILE_W, ++mazeX) {
- bool isVisited = map._visited[mazeY * MAP_W + mazeX];
+ byte visited = map._visited[mazeY * MAP_W + mazeX];
- if (!isVisited) {
+ if (!visited) {
g_globals->_tileSprites.draw(&s, 1,
Common::Point(xp, yp));
} else {
@@ -72,9 +72,17 @@ void Map::draw() {
int wallsE = (walls >> 4) & 3;
int wallsN = (walls >> 6) & 3;
- // Color visited cells in black, and have a line
- // on the edges representing walls vs doors
- s.fillRect(r, 0);
+ // Color visited cells in a color depending on the cell type,
+ // and have a line on the edges representing walls vs doors
+ if (visited == Maps::VISITED_NORMAL)
+ s.fillRect(r, 0);
+ else if (visited == Maps::VISITED_SPECIAL)
+ s.fillRect(r, 0x10);
+ else if (visited == Maps::VISITED_EXIT)
+ s.fillRect(r, 0x20);
+ else if (visited == Maps::VISITED_BUSINESS)
+ s.fillRect(r, 0x30);
+
if (wallsN != Maps::WALL_NONE)
s.hLine(r.left, r.top, r.right - 1,
wallsN == Maps::WALL_DOOR ? 128 : 255);
Commit: c9de1fb0f21ff9142a06d1496f6a211d23be36e9
https://github.com/scummvm/scummvm/commit/c9de1fb0f21ff9142a06d1496f6a211d23be36e9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: Fixes to Gypsy in map 23
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/gypsy.cpp
engines/mm/utils/strings_data.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 02a523ba433..0de95f6e094 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1275,17 +1275,17 @@ maps:
cheers: "CHEERS!"
avalanche: "AVALANCHE!"
look_out: "LOOK OUT!"
- gypsy: "A TOOTHLESS GYPSY SEER ASKS,""WHO WOULD\nLIKE TO HEAR THEIR SIGN (1-6)?"""
- your_sign_is: """YOUR SIGN IS THE"
+ gypsy: "A TOOTHLESS GYPSY SEER ASKS, ""WHO WOULD\nLIKE TO HEAR THEIR SIGN (1-6)?"""
+ your_sign_is: """YOUR SIGN IS THE %s"""
signs:
- 0: "RED THORAC"""
- 1: "BLUE OGRAM"""
- 2: "GREEN BAGAR"""
- 3: "YELLOW LIMRA"""
- 4: "PURPLE SAGRAN"""
- 5: "ORANGE OOLAK"""
- 6: "BLACK DRESIDION"""
- 7: "WHITE DILITHIUM"""
+ 0: "RED THORAC"
+ 1: "BLUE OGRAM"
+ 2: "GREEN BAGAR"
+ 3: "YELLOW LIMRA"
+ 4: "PURPLE SAGRAN"
+ 5: "ORANGE OOLAK"
+ 6: "BLACK DRESIDION"
+ 7: "WHITE DILITHIUM"
map24:
wyverns: "WYVERNS ATTACK FROM ABOVE!"
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index b723f53d12d..dba4cbbbba7 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -55,6 +55,7 @@
#include "mm/mm1/views/maps/dog_statue.h"
#include "mm/mm1/views/maps/ghost.h"
#include "mm/mm1/views/maps/giant.h"
+#include "mm/mm1/views/maps/gypsy.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/views/maps/keeper.h"
@@ -121,6 +122,7 @@ private:
Views::Maps::DogStatue _dogStatue;
Views::Maps::Ghost _ghost;
Views::Maps::Giant _giant;
+ Views::Maps::Gypsy _gypsy;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Inspectron _inspectron;
Views::Maps::Keeper _keeper;
diff --git a/engines/mm/mm1/views/maps/gypsy.cpp b/engines/mm/mm1/views/maps/gypsy.cpp
index 2e69ae95785..9d9436f6550 100644
--- a/engines/mm/mm1/views/maps/gypsy.cpp
+++ b/engines/mm/mm1/views/maps/gypsy.cpp
@@ -70,13 +70,16 @@ void Gypsy::modeChanged(bool allowSelection) {
void Gypsy::draw() {
clearSurface();
if (!_character) {
- writeString(0, 1, STRING["maps.map24.gypsy"]);
+ writeString(0, 1, STRING["maps.map23.gypsy"]);
+
} else {
- Common::String line = Common::String::format("%s %s",
- STRING["maps.map24.your_sign_is"].c_str(),
- STRING[Common::String::format("maps.map24.signs.%d",
+ Common::String line = Common::String::format(
+ STRING["maps.map23.your_sign_is"].c_str(),
+ STRING[Common::String::format("maps.map23.signs.%d",
_character->_flags[4] & CHARFLAG4_SIGN)].c_str()
);
+
+ writeString(0, 1, line);
}
}
@@ -84,10 +87,8 @@ bool Gypsy::msgKeypress(const KeypressMessage &msg) {
if (_character) {
_character = nullptr;
modeChanged(true);
- } else if (msg.keycode >= Common::KEYCODE_1 &&
- msg.keycode <= Common::KEYCODE_6) {
- uint idx = msg.keycode - Common::KEYCODE_1;
- charSelected(idx);
+ draw();
+
} else {
close();
}
@@ -96,8 +97,8 @@ bool Gypsy::msgKeypress(const KeypressMessage &msg) {
}
bool Gypsy::msgAction(const ActionMessage &msg) {
- if (_character && msg._action >= KEYBIND_VIEW_PARTY1 &&
- msg._action <= KEYBIND_VIEW_PARTY6) {
+ if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
uint idx = msg._action - KEYBIND_VIEW_PARTY1;
charSelected(idx);
}
diff --git a/engines/mm/utils/strings_data.cpp b/engines/mm/utils/strings_data.cpp
index 270abdf7c45..1aa979e4e7d 100644
--- a/engines/mm/utils/strings_data.cpp
+++ b/engines/mm/utils/strings_data.cpp
@@ -66,7 +66,7 @@ bool StringsData::load(const Common::String &filename) {
if (value.hasPrefix("\"") && value.hasSuffix("\"")) {
value.deleteChar(0);
value.deleteLastChar();
- value = searchAndReplace(value, "\"\"", "");
+ value = searchAndReplace(value, "\"\"", "\"");
}
// Replace any sequences
Commit: a2c9c9b1108571fce0e39b8536567c5db7c0f1bf
https://github.com/scummvm/scummvm/commit/a2c9c9b1108571fce0e39b8536567c5db7c0f1bf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: Draw new map position before triggering specials
Changed paths:
engines/mm/mm1/game/view_base.cpp
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index afb6969b5c0..160056e2956 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -59,6 +59,8 @@ darkness:
g_globals->_encounters._encounterType = NORMAL_SURPRISED;
if (maps._currentState & Maps::CELL_SPECIAL) {
map.visitedSpecial();
+ draw();
+
map.special();
} else if (_stepRandom) {
Commit: 71f22c251c4a5a4ec75acfcd6ba825a438bcce27
https://github.com/scummvm/scummvm/commit/71f22c251c4a5a4ec75acfcd6ba825a438bcce27
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: Tavern fixes
Changed paths:
engines/mm/mm1/views/locations/tavern.cpp
diff --git a/engines/mm/mm1/views/locations/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
index 53e87b06c9d..a5c2417d3ff 100644
--- a/engines/mm/mm1/views/locations/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -40,10 +40,19 @@ bool Tavern::msgFocus(const FocusMessage &msg) {
}
bool Tavern::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
leave();
- break;
+ return true;
+ }
+
+ // If timed message display, end the waiting
+ if (isDelayActive()) {
+ cancelDelay();
+ timeout();
+ return true;
+ }
+
+ switch (msg.keycode) {
case Common::KEYCODE_a:
haveADrink();
break;
@@ -106,7 +115,7 @@ void Tavern::tipBartender() {
if (g_globals->_currCharacter->_numDrinks == 0) {
displayMessage(STRING["dialogs.tavern.have_a_drink"]);
} else if (g_engine->getRandomNumber(3) != 3) {
- displayMessage(STRING["dialogs.tavern.have_another_drink"]);
+ displayMessage(STRING["dialogs.tavern.have_another_round"]);
} else {
int townNum = g_maps->_currentMap->dataByte(Maps::MAP_ID);
displayMessage(STRING[Common::String::format(
Commit: e9abe95d7ea6efa1f9d08b85ce6cf3a7030172fe
https://github.com/scummvm/scummvm/commit/e9abe95d7ea6efa1f9d08b85ce6cf3a7030172fe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: Added endDelay method for expiring timeouts
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/locations/statue.cpp
engines/mm/mm1/views/locations/tavern.cpp
engines/mm/mm1/views/maps/giant.cpp
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/trap.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index c754dccbc0e..2b167f58de2 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -105,6 +105,14 @@ protected:
_timeoutCtr = 0;
}
+ /**
+ * Ends an active delay and calls timeout
+ */
+ void endDelay() {
+ _timeoutCtr = 0;
+ timeout();
+ }
+
/**
* Called when an active timeout countdown expired
*/
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 44b6c7221e8..2adc057d116 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -249,8 +249,7 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
} else if (isDelayActive()) {
// In all other modes, if a delay is active, any keypress
// will cause the delay to end immediately
- cancelDelay();
- timeout();
+ endDelay();
}
return true;
diff --git a/engines/mm/mm1/views/locations/statue.cpp b/engines/mm/mm1/views/locations/statue.cpp
index 8a588d78233..c67088576fc 100644
--- a/engines/mm/mm1/views/locations/statue.cpp
+++ b/engines/mm/mm1/views/locations/statue.cpp
@@ -43,7 +43,12 @@ bool Statue::msgValue(const ValueMessage &msg) {
}
bool Statue::msgKeypress(const KeypressMessage &msg) {
- leave();
+ if (isDelayActive()) {
+ endDelay();
+ } else {
+ leave();
+ }
+
return true;
}
diff --git a/engines/mm/mm1/views/locations/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
index a5c2417d3ff..11477a3429f 100644
--- a/engines/mm/mm1/views/locations/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -47,8 +47,7 @@ bool Tavern::msgKeypress(const KeypressMessage &msg) {
// If timed message display, end the waiting
if (isDelayActive()) {
- cancelDelay();
- timeout();
+ endDelay();
return true;
}
diff --git a/engines/mm/mm1/views/maps/giant.cpp b/engines/mm/mm1/views/maps/giant.cpp
index 66307374b39..b163a29e8e5 100644
--- a/engines/mm/mm1/views/maps/giant.cpp
+++ b/engines/mm/mm1/views/maps/giant.cpp
@@ -50,8 +50,8 @@ void Giant::draw() {
bool Giant::msgKeypress(const KeypressMessage &msg) {
if (isDelayActive()) {
- cancelDelay();
- redraw();
+ endDelay();
+ draw();
} else if (msg.keycode < Common::KEYCODE_1 ||
msg.keycode > Common::KEYCODE_6) {
close();
@@ -65,8 +65,8 @@ bool Giant::msgKeypress(const KeypressMessage &msg) {
bool Giant::msgAction(const ActionMessage &msg) {
if (isDelayActive()) {
- cancelDelay();
- redraw();
+ endDelay();
+
} else if (msg._action >= KEYBIND_VIEW_PARTY1 &&
msg._action <= KEYBIND_VIEW_PARTY6) {
uint idx = msg._action - KEYBIND_VIEW_PARTY1;
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 57055fe4256..74d59968d4d 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -105,8 +105,7 @@ void Search::draw() {
bool Search::msgKeypress(const KeypressMessage &msg) {
switch (_mode) {
case INITIAL:
- cancelDelay();
- timeout();
+ endDelay();
break;
case OPTIONS:
@@ -130,8 +129,7 @@ bool Search::msgKeypress(const KeypressMessage &msg) {
case RESPONSE:
if (isDelayActive()) {
- cancelDelay();
- timeout();
+ endDelay();
}
break;
diff --git a/engines/mm/mm1/views/trap.cpp b/engines/mm/mm1/views/trap.cpp
index 4f995b29d79..ff43948fc4d 100644
--- a/engines/mm/mm1/views/trap.cpp
+++ b/engines/mm/mm1/views/trap.cpp
@@ -57,9 +57,7 @@ void Trap::draw() {
}
bool Trap::msgKeypress(const KeypressMessage &msg) {
- cancelDelay();
- timeout();
-
+ endDelay();
return true;
}
Commit: b1b765b38ae08aa445d792dc4d4d2ec20e7f83ff
https://github.com/scummvm/scummvm/commit/b1b765b38ae08aa445d792dc4d4d2ec20e7f83ff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: Made endDelay return a bool for if delay was active
Changed paths:
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/views/locations/statue.cpp
engines/mm/mm1/views/locations/tavern.cpp
engines/mm/mm1/views/maps/giant.cpp
engines/mm/mm1/views/search.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 6734d5175b9..16f865c0a03 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -324,6 +324,16 @@ void UIElement::delayFrames(uint frames) {
_timeoutCtr = frames;
}
+bool UIElement::endDelay() {
+ if (_timeoutCtr) {
+ _timeoutCtr = 0;
+ timeout();
+ return true;
+ } else {
+ return false;
+ }
+}
+
void UIElement::timeout() {
redraw();
}
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 2b167f58de2..308e31eced9 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -108,10 +108,7 @@ protected:
/**
* Ends an active delay and calls timeout
*/
- void endDelay() {
- _timeoutCtr = 0;
- timeout();
- }
+ bool endDelay();
/**
* Called when an active timeout countdown expired
diff --git a/engines/mm/mm1/views/locations/statue.cpp b/engines/mm/mm1/views/locations/statue.cpp
index c67088576fc..e3ae7652e0b 100644
--- a/engines/mm/mm1/views/locations/statue.cpp
+++ b/engines/mm/mm1/views/locations/statue.cpp
@@ -43,11 +43,8 @@ bool Statue::msgValue(const ValueMessage &msg) {
}
bool Statue::msgKeypress(const KeypressMessage &msg) {
- if (isDelayActive()) {
- endDelay();
- } else {
+ if (!endDelay())
leave();
- }
return true;
}
diff --git a/engines/mm/mm1/views/locations/tavern.cpp b/engines/mm/mm1/views/locations/tavern.cpp
index 11477a3429f..93b3986cad4 100644
--- a/engines/mm/mm1/views/locations/tavern.cpp
+++ b/engines/mm/mm1/views/locations/tavern.cpp
@@ -46,10 +46,8 @@ bool Tavern::msgKeypress(const KeypressMessage &msg) {
}
// If timed message display, end the waiting
- if (isDelayActive()) {
- endDelay();
+ if (endDelay())
return true;
- }
switch (msg.keycode) {
case Common::KEYCODE_a:
diff --git a/engines/mm/mm1/views/maps/giant.cpp b/engines/mm/mm1/views/maps/giant.cpp
index b163a29e8e5..36db4b9599a 100644
--- a/engines/mm/mm1/views/maps/giant.cpp
+++ b/engines/mm/mm1/views/maps/giant.cpp
@@ -49,12 +49,13 @@ void Giant::draw() {
}
bool Giant::msgKeypress(const KeypressMessage &msg) {
- if (isDelayActive()) {
- endDelay();
+ if (endDelay()) {
draw();
+
} else if (msg.keycode < Common::KEYCODE_1 ||
msg.keycode > Common::KEYCODE_6) {
close();
+
} else {
uint charIndex = msg.keycode - Common::KEYCODE_1;
charSelected(charIndex);
@@ -64,8 +65,8 @@ bool Giant::msgKeypress(const KeypressMessage &msg) {
}
bool Giant::msgAction(const ActionMessage &msg) {
- if (isDelayActive()) {
- endDelay();
+ if (endDelay()) {
+ // Nothing further
} else if (msg._action >= KEYBIND_VIEW_PARTY1 &&
msg._action <= KEYBIND_VIEW_PARTY6) {
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 74d59968d4d..b39af3b0274 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -128,9 +128,7 @@ bool Search::msgKeypress(const KeypressMessage &msg) {
break;
case RESPONSE:
- if (isDelayActive()) {
- endDelay();
- }
+ endDelay();
break;
case WHO_WILL_TRY:
Commit: 413b30ee9db3436bfe9d736a81f98bf9cd84c14b
https://github.com/scummvm/scummvm/commit/413b30ee9db3436bfe9d736a81f98bf9cd84c14b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: More use of endDelay
Changed paths:
engines/mm/mm1/views/locations/market.cpp
engines/mm/mm1/views/locations/temple.cpp
engines/mm/mm1/views/locations/training.cpp
engines/mm/mm1/views/maps/volcano_god.cpp
diff --git a/engines/mm/mm1/views/locations/market.cpp b/engines/mm/mm1/views/locations/market.cpp
index dda2f6d7f81..0b53a6c9ac2 100644
--- a/engines/mm/mm1/views/locations/market.cpp
+++ b/engines/mm/mm1/views/locations/market.cpp
@@ -44,6 +44,9 @@ bool Market::msgFocus(const FocusMessage &msg) {
}
bool Market::msgKeypress(const KeypressMessage &msg) {
+ if (endDelay())
+ return true;
+
switch (msg.keycode) {
case Common::KEYCODE_ESCAPE:
case Common::KEYCODE_n:
diff --git a/engines/mm/mm1/views/locations/temple.cpp b/engines/mm/mm1/views/locations/temple.cpp
index 181ae62e1b5..05ff9f411d3 100644
--- a/engines/mm/mm1/views/locations/temple.cpp
+++ b/engines/mm/mm1/views/locations/temple.cpp
@@ -41,10 +41,16 @@ bool Temple::msgFocus(const FocusMessage &msg) {
}
bool Temple::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
leave();
- break;
+ return true;
+ }
+
+ // If a delay is active, end it
+ if (endDelay())
+ return true;
+
+ switch (msg.keycode) {
case Common::KEYCODE_a:
restoreHealth();
break;
diff --git a/engines/mm/mm1/views/locations/training.cpp b/engines/mm/mm1/views/locations/training.cpp
index 218b3e2aabe..360e8cb09f5 100644
--- a/engines/mm/mm1/views/locations/training.cpp
+++ b/engines/mm/mm1/views/locations/training.cpp
@@ -117,10 +117,16 @@ void Training::draw() {
}
bool Training::msgKeypress(const KeypressMessage &msg) {
- switch (msg.keycode) {
- case Common::KEYCODE_ESCAPE:
+ if (msg.keycode == Common::KEYCODE_ESCAPE) {
leave();
- break;
+ return true;
+ }
+
+ // If a delay is active, end it
+ if (endDelay())
+ return true;
+
+ switch (msg.keycode) {
case Common::KEYCODE_a:
if (_canTrain)
train();
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
index fb3b3ab6ff9..ddef9fe964d 100644
--- a/engines/mm/mm1/views/maps/volcano_god.cpp
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -56,27 +56,28 @@ void VolcanoGod::draw() {
}
bool VolcanoGod::msgKeypress(const KeypressMessage &msg) {
- if (!isDelayActive()) {
- switch (_mode) {
- case CHOOSE_OPTION:
- switch (msg.keycode) {
- case Common::KEYCODE_a:
- challenge();
- break;
- case Common::KEYCODE_b:
- riddle();
- break;
- case Common::KEYCODE_c:
- clue();
- break;
- default:
- break;
- }
- break;
+ if (endDelay())
+ return true;
- case ENTER_RESPONSE:
- return AnswerEntry::msgKeypress(msg);
+ switch (_mode) {
+ case CHOOSE_OPTION:
+ switch (msg.keycode) {
+ case Common::KEYCODE_a:
+ challenge();
+ break;
+ case Common::KEYCODE_b:
+ riddle();
+ break;
+ case Common::KEYCODE_c:
+ clue();
+ break;
+ default:
+ break;
}
+ break;
+
+ case ENTER_RESPONSE:
+ return AnswerEntry::msgKeypress(msg);
}
return true;
Commit: 167d06736690c7b03c7013267abd2a24edce63db
https://github.com/scummvm/scummvm/commit/167d06736690c7b03c7013267abd2a24edce63db
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: Map 23 fixes
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/console.h
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/views/text_view.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 3a452d47a6c..20e5f7868fd 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -43,6 +43,7 @@ Console::Console() : GUI::Debugger() {
registerCmd("encounter", WRAP_METHOD(Console, cmdEncounter));
registerCmd("encounters", WRAP_METHOD(Console, cmdEncounters));
registerCmd("specials", WRAP_METHOD(Console, cmdSpecials));
+ registerCmd("special", WRAP_METHOD(Console, cmdSpecial));
}
bool Console::cmdDumpMap(int argc, const char **argv) {
@@ -392,5 +393,38 @@ bool Console::cmdSpecials(int argc, const char **argv) {
return true;
}
+bool Console::cmdSpecial(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("special <num> to execute special in the current map\n");
+ return true;
+ }
+
+ Maps::Maps &maps = *g_maps;
+ Maps::Map &map = *g_maps->_currentMap;
+ uint count = g_maps->_currentMap->dataByte(Maps::MAP_SPECIAL_COUNT);
+ uint specialNum = strToInt(argv[1]);
+
+ if (specialNum > count) {
+ debugPrintf("Invalid special number\n");
+ return true;
+ }
+
+ // Set new position
+ maps._mapOffset = map[51 + specialNum];
+ maps._mapPos.x = maps._mapOffset % 16;
+ maps._mapPos.y = maps._mapOffset / 16;
+
+ // Rotate to find a direction that will trigger the special
+ for (int i = 0; i < 4; ++i) {
+ if (maps._forwardMask & map[51 + count + specialNum])
+ break;
+ maps.turnLeft();
+ }
+
+ // Execute the specials handler for the map
+ map.special();
+ return false;
+}
+
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/console.h b/engines/mm/mm1/console.h
index 7d095ae5887..625e3d3f407 100644
--- a/engines/mm/mm1/console.h
+++ b/engines/mm/mm1/console.h
@@ -85,6 +85,11 @@ protected:
*/
bool cmdSpecials(int argc, const char **argv);
+ /**
+ * Trigger a special in the current map
+ */
+ bool cmdSpecial(int argc, const char **argv);
+
public:
Console();
~Console() override {}
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index f9604fbd405..cd701eca815 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -74,7 +74,7 @@ void Map23::special01() {
send(SoundMessage(
STRING["maps.map23.cave"],
[]() {
- g_maps->_mapPos = Common::Point(2, 0);
+ g_maps->_mapPos = Common::Point(7, 0);
g_maps->changeMap(1, 1);
}
));
@@ -112,7 +112,7 @@ void Map23::special03() {
void Map23::special08() {
send(SoundMessage(
- STRING["maps.map19.column"],
+ STRING["maps.map23.column"],
[]() {
g_maps->_mapPos = Common::Point(
getRandomNumber(15), getRandomNumber(15));
@@ -123,7 +123,7 @@ void Map23::special08() {
void Map23::special09() {
send(SoundMessage(
- STRING["maps.map19.statues"],
+ STRING["maps.map23.statues"],
[]() {
Map23 &map = *static_cast<Map23 *>(g_maps->_currentMap);
Game::Encounter &enc = g_globals->_encounters;
@@ -169,7 +169,7 @@ void Map23::special11() {
}
void Map23::special12() {
- send(SoundMessage(14, 22, STRING["maps.map23.avalanche"]));
+ send(SoundMessage(14, 2, STRING["maps.map23.avalanche"]));
g_maps->_currentState = 209;
_states[g_maps->_mapOffset] = 0xff;
_walls[g_maps->_mapOffset] = 162;
@@ -196,7 +196,6 @@ void Map23::fountain() {
[]() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- g_globals->_currCharacter = &c;
int attrNum = getRandomNumber(8) - 1;
c.getAttribute(attrNum)._current = 30;
}
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 87f17e91d14..b5f39eb0d8c 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -60,7 +60,8 @@ void TextView::writeChar(int x, int y, unsigned char c) {
void TextView::writeString(const Common::String &str) {
for (const unsigned char *s = (const unsigned char *)str.c_str(); *s; ++s) {
- writeChar(*s);
+ if (*s != '|')
+ writeChar(*s);
}
}
Commit: 0a036066a63b937268b1276d91344db4bbe06812
https://github.com/scummvm/scummvm/commit/0a036066a63b937268b1276d91344db4bbe06812
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:43+01:00
Commit Message:
MM: MM1: Map changes fixes
Changed paths:
engines/mm/mm1/game/spells_party.cpp
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/mm1.cpp
diff --git a/engines/mm/mm1/game/spells_party.cpp b/engines/mm/mm1/game/spells_party.cpp
index f793206951b..e678adce3fb 100644
--- a/engines/mm/mm1/game/spells_party.cpp
+++ b/engines/mm/mm1/game/spells_party.cpp
@@ -425,9 +425,8 @@ SpellResult SpellsParty::cleric48_surface() {
} else {
maps._mapPos = Common::Point(map[Maps::MAP_SURFACE_X],
map[Maps::MAP_SURFACE_Y]);
- maps.changeMap(map[Maps::MAP_SURFACE_DEST_ID1] &
- (map[Maps::MAP_SURFACE_DEST_ID2] << 8),
- map[Maps::MAP_SURFACE_DEST_SECTION]);
+ maps.changeMap(map.dataWord(Maps::MAP_SURFACE_ID),
+ map[Maps::MAP_SURFACE_SECTION]);
return SR_SUCCESS_SILENT;
}
}
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 160056e2956..21581382d12 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -237,7 +237,6 @@ void ViewBase::obstructed(byte mask) {
_dialogMessage = STRING[Common::String::format(
"movement.obstructed.%d", map.dataByte(index))];
-
}
void ViewBase::barrier() {
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index b1f3eb08b7b..7f13a00a1f7 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -43,16 +43,14 @@ enum DataOffset {
MAP_2 = 2,
MAP_4 = 4,
MAP_6 = 6,
- MAP_8 = 8,
- MAP_10 = 10,
- MAP_SURFACE_DEST_ID1 = 11,
- MAP_SURFACE_DEST_ID2 = 12,
- MAP_SURFACE_DEST_SECTION = 13,
- MAP_14 = 14,
- MAP_16 = 16,
- MAP_17 = 17,
- MAP_18 = 18,
- MAP_19 = 19,
+ MAP_NORTH_EXIT_ID = 8,
+ MAP_NORTH_EXIT_SECTION = 10,
+ MAP_EAST_EXIT_ID = 11,
+ MAP_EAST_EXIT_SECTION = 13,
+ MAP_WEST_EXIT_SECTION = 17,
+ MAP_WEST_EXIT_ID = 19,
+ MAP_SOUTH_EXIT_ID = 14,
+ MAP_SOUTH_EXIT_SECTION = 16,
MAP_20 = 20,
MAP_21 = 21,
MAP_FLEE_THRESHOLD = 22,
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index cd701eca815..4b525d10da2 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -129,7 +129,8 @@ void Map23::special09() {
Game::Encounter &enc = g_globals->_encounters;
g_maps->clearSpecial();
- map._walls[32]--;
+ map._states[32]--;
+ g_maps->_currentState = map._states[32];
enc.clearMonsters();
for (int i = 0; i < 6; ++i)
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 18ca6c0f4d4..6694761e4d2 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -429,26 +429,27 @@ void Maps::turnAround() {
void Maps::step(const Common::Point &delta) {
_mapPos += delta;
byte &visited = _currentMap->_visited[_mapPos.y * MAP_W + _mapPos.x];
- if (!visited)
+ if (!visited) {
visited = VISITED_NORMAL;
+ }
int section = 0, id = 0;
if (_mapPos.x < 0) {
_mapPos.x = MAP_W - 1;
- id = _currentMap->dataWord(MAP_16);
- section = _currentMap->dataByte(MAP_14);
+ id = _currentMap->dataWord(MAP_WEST_EXIT_ID);
+ section = _currentMap->dataByte(MAP_WEST_EXIT_SECTION);
} else if (_mapPos.x >= MAP_W) {
_mapPos.x = 0;
- id = _currentMap->dataWord(MAP_SURFACE_DEST_ID1);
- section = _currentMap->dataByte(MAP_SURFACE_DEST_SECTION);
+ id = _currentMap->dataWord(MAP_EAST_EXIT_ID);
+ section = _currentMap->dataByte(MAP_EAST_EXIT_SECTION);
} else if (_mapPos.y < 0) {
_mapPos.y = MAP_H - 1;
- id = _currentMap->dataWord(MAP_17);
- section = _currentMap->dataByte(MAP_19);
+ id = _currentMap->dataWord(MAP_SOUTH_EXIT_ID);
+ section = _currentMap->dataByte(MAP_SOUTH_EXIT_SECTION);
} else if (_mapPos.y >= MAP_H) {
_mapPos.y = 0;
- id = _currentMap->dataWord(MAP_8);
- section = _currentMap->dataByte(MAP_10);
+ id = _currentMap->dataWord(MAP_NORTH_EXIT_ID);
+ section = _currentMap->dataByte(MAP_NORTH_EXIT_SECTION);
} else {
return;
}
diff --git a/engines/mm/mm1/mm1.cpp b/engines/mm/mm1/mm1.cpp
index b11417f3b87..062e9634fc9 100644
--- a/engines/mm/mm1/mm1.cpp
+++ b/engines/mm/mm1/mm1.cpp
@@ -62,6 +62,9 @@ Common::Error MM1Engine::run() {
// Setup console
setDebugger(new Console());
+ if (gDebugLevel > 0)
+ // TODO: Remove flag once everything is tested
+ g_globals->_encountersOn = false;
// Load globals
if (!_globals.load(isEnhanced()))
Commit: d492eb526508a7c8ab7c884bf11b2814f0cc47b3
https://github.com/scummvm/scummvm/commit/d492eb526508a7c8ab7c884bf11b2814f0cc47b3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Map fixes
Changed paths:
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 7f13a00a1f7..b6e14ce5123 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -47,10 +47,10 @@ enum DataOffset {
MAP_NORTH_EXIT_SECTION = 10,
MAP_EAST_EXIT_ID = 11,
MAP_EAST_EXIT_SECTION = 13,
- MAP_WEST_EXIT_SECTION = 17,
- MAP_WEST_EXIT_ID = 19,
MAP_SOUTH_EXIT_ID = 14,
MAP_SOUTH_EXIT_SECTION = 16,
+ MAP_WEST_EXIT_ID = 17,
+ MAP_WEST_EXIT_SECTION = 19,
MAP_20 = 20,
MAP_21 = 21,
MAP_FLEE_THRESHOLD = 22,
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index c17a281c4a2..b5f11b17ee6 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -106,10 +106,10 @@ void Map20::special02() {
[](const Common::KeyState &ks) {
Map20 &map = *static_cast<Map20 *>(g_maps->_currentMap);
if (ks.keycode == Common::KEYCODE_y) {
- g_events->close();
+ g_events->focusedView()->close();
map[VAL1] = 0xff;
} else if (ks.keycode == Common::KEYCODE_n) {
- g_events->close();
+ g_events->focusedView()->close();
map[VAL1]++;
}
}
@@ -130,15 +130,15 @@ void Map20::special03() {
send(
SoundMessage(STRING["maps.map20.castle"],
[](const Common::KeyState &) {
- g_events->close();
+ g_events->focusedView()->close();
g_events->send(SoundMessage(
STRING["maps.map20.whistle"],
[](const Common::KeyState &ks) {
if (ks.keycode == Common::KEYCODE_0) {
- g_events->close();
+ g_events->focusedView()->close();
none160();
} else if (ks.keycode == Common::KEYCODE_2) {
- g_events->close();
+ g_events->focusedView()->close();
g_events->send(SoundMessage(
STRING["maps.map20.stairs_down"],
[]() {
@@ -154,7 +154,7 @@ void Map20::special03() {
} else if (ks.keycode >= Common::KEYCODE_1 &&
ks.keycode <= Common::KEYCODE_9) {
- g_events->close();
+ g_events->focusedView()->close();
g_maps->_mapPos = Common::Point(8, 5);
g_maps->changeMap(0x604, 1);
}
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index d4e87c7fc02..65be981c263 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -58,6 +58,7 @@ void Map24::special01() {
send(SoundMessage(
STRING["maps.map24.kilburn"],
[]() {
+ g_events->focusedView()->close();
Map24 &map = *static_cast<Map24 *>(g_maps->_currentMap);
if (!map.addItem(MAP_OF_DESERT_ID))
none160();
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 6694761e4d2..c254c23e399 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -121,7 +121,7 @@ static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
static byte TILE_COLORS[18] = {
0xe6, 0xe6, 0xe6, 0x72, 0x72, 0x72, 0x62, 0x62, 0x62,
- 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0x62, 0x62, 0x62, 0, 0, 0, 0, 0, 0
};
Maps::Maps() {
Commit: 5a17caf565f1d9f45952ed4fb0b47b6987823eaf
https://github.com/scummvm/scummvm/commit/5a17caf565f1d9f45952ed4fb0b47b6987823eaf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Map 24 fixes
Changed paths:
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/text_view.cpp
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index 65be981c263..ebe24573497 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -55,15 +55,19 @@ void Map24::special00() {
}
void Map24::special01() {
- send(SoundMessage(
+ SoundMessage msg(
STRING["maps.map24.kilburn"],
[]() {
- g_events->focusedView()->close();
Map24 &map = *static_cast<Map24 *>(g_maps->_currentMap);
- if (!map.addItem(MAP_OF_DESERT_ID))
+ if (!map.addItem(MAP_OF_DESERT_ID)) {
+ g_maps->clearSpecial();
none160();
+ }
}
- ));
+ );
+ msg._largeMessage = true;
+
+ send(msg);
}
void Map24::special02() {
@@ -130,8 +134,6 @@ void Map24::special09() {
[]() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- g_globals->_currCharacter = &c;
-
c._backpack.clear();
for (int j = 0; j < INVENTORY_COUNT; ++j)
c._backpack.add(USELESS_ITEM_ID, 0);
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 4ee28faa345..70190612951 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -105,8 +105,11 @@ bool GameMessages::msgKeypress(const KeypressMessage &msg) {
}
void GameMessages::timeout() {
- if (_ynCallback)
+ if (_ynCallback) {
+ // _ynCallback is also used for timeout callbacks
+ close();
_ynCallback();
+ }
}
} // namespace Views
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index b5f39eb0d8c..3dc7588bc12 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -62,6 +62,12 @@ void TextView::writeString(const Common::String &str) {
for (const unsigned char *s = (const unsigned char *)str.c_str(); *s; ++s) {
if (*s != '|')
writeChar(*s);
+
+ if (*s >= ' ' && _textPos.x == 0 && (*(s + 1) == '\r' || *(s + 1) == '\n'))
+ // Ignore carraige returns right after line wraps. The original didn't
+ // have them and just carried on immedaitely with the next word,
+ // but I wanted them to be present to cleanly identify line breaks
+ ++s;
}
}
Commit: c77c2fdda7a74ebbbbe64722fabb2d0298139840
https://github.com/scummvm/scummvm/commit/c77c2fdda7a74ebbbbe64722fabb2d0298139840
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Map 20 fixexs
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/game/view_base.cpp
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map20.h
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/text_view.cpp
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index c8965f46085..0cd594ca92c 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -68,6 +68,12 @@ Graphics::ManagedSurface Monsters::getMonsterImage(int monsterNum) {
// Decode the image
Graphics::ManagedSurface img;
Gfx::ScreenDecoder decoder;
+ // TODO: Figure out if the indexes are map-dependant
+ decoder._indexes[0] = 0;
+ decoder._indexes[1] = 2;
+ decoder._indexes[2] = 4;
+ decoder._indexes[3] = 15;
+
if (!decoder.loadStream(*entry, 104, 96))
error("Failed decoding monster image");
diff --git a/engines/mm/mm1/game/view_base.cpp b/engines/mm/mm1/game/view_base.cpp
index 21581382d12..3e95d229c87 100644
--- a/engines/mm/mm1/game/view_base.cpp
+++ b/engines/mm/mm1/game/view_base.cpp
@@ -62,6 +62,7 @@ darkness:
draw();
map.special();
+ return;
} else if (_stepRandom) {
g_globals->_encounters._encounterType = NORMAL_ENCOUNTER;
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index b5f11b17ee6..8cd67350f1f 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -29,7 +29,7 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 177
+#define CASTLE_STATE 177
void Map20::special() {
Game::Encounter &enc = g_globals->_encounters;
@@ -93,24 +93,28 @@ void Map20::special01() {
void Map20::special02() {
visitedExit();
- if (_data[VAL1] & 0x80) {
- g_maps->_mapPos = Common::Point(15, 8);
- g_maps->changeMap(0xa11, 3);
+ if (_data[CASTLE_STATE] & 0x80) {
+ goToCastle();
- } else if (_data[VAL1]) {
- _data[VAL1] = 0;
+ } else if (_data[CASTLE_STATE]) {
+ _data[CASTLE_STATE] = 0;
} else {
+ send("View", DrawGraphicMessage(6 + 65));
+
send(SoundMessage(
- STRING["maps.map20.cave"],
+ STRING["maps.map20.castle"],
[](const Common::KeyState &ks) {
Map20 &map = *static_cast<Map20 *>(g_maps->_currentMap);
if (ks.keycode == Common::KEYCODE_y) {
g_events->focusedView()->close();
- map[VAL1] = 0xff;
+ map[CASTLE_STATE] = 0xff;
+ map.goToCastle();
+
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->focusedView()->close();
- map[VAL1]++;
+ map[CASTLE_STATE]++;
+ map.updateGame();
}
}
));
@@ -118,17 +122,19 @@ void Map20::special02() {
}
void Map20::special03() {
- bool hasWhistle = false;
- for (uint i = 0; i < g_globals->_party.size() && !hasWhistle; ++i)
- hasWhistle = g_globals->_party[i].hasItem(RUBY_WHISTLE_ID);
+ bool hasWhistle = g_globals->_party.hasItem(RUBY_WHISTLE_ID);
if (!hasWhistle) {
- send(SoundMessage(STRING["maps.map20.castle"]));
+ send(SoundMessage(STRING["maps.map20.temple"],
+ [](const Common::KeyState &) {
+ g_events->focusedView()->close();
+ }
+ ));
return;
}
send(
- SoundMessage(STRING["maps.map20.castle"],
+ SoundMessage(STRING["maps.map20.temple"],
[](const Common::KeyState &) {
g_events->focusedView()->close();
g_events->send(SoundMessage(
@@ -193,6 +199,11 @@ void Map20::special08() {
updateGame();
}
+void Map20::goToCastle() {
+ g_maps->_mapPos = Common::Point(15, 8);
+ g_maps->changeMap(0xa11, 3);
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map20.h b/engines/mm/mm1/maps/map20.h
index ccb0583214d..72f3a262731 100644
--- a/engines/mm/mm1/maps/map20.h
+++ b/engines/mm/mm1/maps/map20.h
@@ -59,6 +59,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Go to the castle
+ */
+ void goToCastle();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index c254c23e399..e8360a8cb84 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -121,7 +121,7 @@ static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
static byte TILE_COLORS[18] = {
0xe6, 0xe6, 0xe6, 0x72, 0x72, 0x72, 0x62, 0x62, 0x62,
- 0x62, 0x62, 0x62, 0, 0, 0, 0, 0, 0
+ 0x62, 0x62, 0xe1, 0, 0, 0, 0, 0, 0
};
Maps::Maps() {
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 70190612951..29ccc6e6a9d 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -54,10 +54,6 @@ void GameMessages::draw() {
bool GameMessages::msgInfo(const InfoMessage &msg) {
if (msg._ynCallback || msg._keyCallback ||
g_globals->_party.isPartyDead()) {
- // Do a first draw to show 3d view at new position
- g_events->redraw();
- g_events->drawElements();
-
addView(this);
}
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 3dc7588bc12..4d1b54f3aaf 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -143,10 +143,10 @@ void TextView::timeout() {
}
bool TextView::msgDrawGraphic(const DrawGraphicMessage &msg) {
- Graphics::ManagedSurface img =
+ const Graphics::ManagedSurface img =
g_globals->_monsters.getMonsterImage(msg._gfxNum);
getSurface().blitFrom(img, Common::Point(64, 16));
- return true;
+ return true;
}
} // namespace Views
Commit: 680b63087e78f9ebe61b48f4311ce2560883cef8
https://github.com/scummvm/scummvm/commit/680b63087e78f9ebe61b48f4311ce2560883cef8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Map 43 fixes
Changed paths:
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/views/maps/lord_ironfist.cpp
engines/mm/mm1/views/maps/prisoners.cpp
engines/mm/mm1/views/maps/prisoners.h
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 4a7449be47b..7e2034073e4 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -87,7 +87,7 @@ void Map43::special02() {
STRING["maps.map43.button"],
[]() {
Map43 &map = *static_cast<Map43 *>(g_maps->_currentMap);
- map._walls[101] = 17;
+ map._states[101] = 17;
map.none160();
}
));
@@ -99,9 +99,14 @@ void Map43::special03() {
void Map43::special04() {
if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
- g_maps->_mapPos = Common::Point(9, 13);
- g_maps->changeMap(0x101, 2);
- send(SoundMessage(STRING["maps.map43.guards"]));
+ send(SoundMessage(
+ STRING["maps.map43.guards"],
+ [](const Common::KeyState &ks) {
+ g_events->focusedView()->close();
+ g_maps->_mapPos = Common::Point(9, 13);
+ g_maps->changeMap(0x101, 2);
+ }
+ ));
}
}
@@ -163,16 +168,20 @@ void Map43::acceptQuest() {
byte flags = leader._flags[10];
// Find quest that hasn't been done yet
- int questNum;
- for (questNum = 0; flags && questNum < 8; ++questNum, flags >>= 1) {
- if (!(flags & 1))
- break;
- }
- if (questNum == 8) {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- c._flags[10] = CHARFLAG8_80;
- c._flags[7] = CHARFLAG5_80;
+ int questNum = 1;
+ if (flags) {
+ for (questNum = 1; flags && questNum < 8; ++questNum, flags >>= 1) {
+ if (!(flags & 1))
+ break;
+ }
+ if (questNum == 8) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[10] = CHARFLAG8_80;
+ c._flags[7] = CHARFLAG5_80;
+ }
+
+ questNum = 1;
}
}
@@ -184,12 +193,12 @@ void Map43::acceptQuest() {
// Draw the scene
g_maps->_mapPos.x++;
- redrawGame();
+ updateGame();
}
Common::String Map43::checkQuestComplete() {
Character &leader = g_globals->_party[0];
- int qIndex = leader._quest - 7;
+ int qIndex = leader._quest - 1;
if (leader._flags[7] & MATCH_FLAGS[qIndex] & 0x7f) {
// The quest was complete
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index e8360a8cb84..13785a89507 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -121,7 +121,7 @@ static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
static byte TILE_COLORS[18] = {
0xe6, 0xe6, 0xe6, 0x72, 0x72, 0x72, 0x62, 0x62, 0x62,
- 0x62, 0x62, 0xe1, 0, 0, 0, 0, 0, 0
+ 0x62, 0x62, 0xe1, 0, 0, 0, 0x43, 0x43, 0x63
};
Maps::Maps() {
diff --git a/engines/mm/mm1/views/maps/lord_ironfist.cpp b/engines/mm/mm1/views/maps/lord_ironfist.cpp
index 5981073dffd..4b9ed7a34fe 100644
--- a/engines/mm/mm1/views/maps/lord_ironfist.cpp
+++ b/engines/mm/mm1/views/maps/lord_ironfist.cpp
@@ -46,10 +46,10 @@ void LordIronfist::draw() {
clearSurface();
if (_canAccept) {
- send(SoundMessage(
- 0, 1, STRING["maps.map43.ironfist1"],
- 0, 2, STRING["maps.map43.ironfist2"]
- ));
+ Sound::sound2(SOUND_2);
+ writeString(0, 1, STRING["maps.map43.ironfist1"]);
+ writeString(0, 2, STRING["maps.map43.ironfist2"]);
+
} else {
int questNum = g_globals->_party[0]._quest;
Common::String line;
@@ -76,18 +76,18 @@ bool LordIronfist::msgKeypress(const KeypressMessage &msg) {
if (_canAccept) {
if (msg.keycode == Common::KEYCODE_y) {
+ close();
map.acceptQuest();
- clearSurface();
- writeString(0, 1, STRING["maps.map43.ironfist1"]);
- writeString(0, 2, STRING[Common::String::format(
- "maps.map43.quests.%d",
- g_globals->_party[0]._quest)]);
- close();
+ send(InfoMessage(
+ 0, 1, STRING["maps.map43.ironfist1"],
+ 0, 2, STRING[Common::String::format(
+ "maps.map43.quests.%d",
+ g_globals->_party[0]._quest)]
+ ));
} else if (msg.keycode == Common::KEYCODE_n) {
close();
- map.redrawGame();
}
}
diff --git a/engines/mm/mm1/views/maps/prisoners.cpp b/engines/mm/mm1/views/maps/prisoners.cpp
index 327660d6ba7..a9bff882272 100644
--- a/engines/mm/mm1/views/maps/prisoners.cpp
+++ b/engines/mm/mm1/views/maps/prisoners.cpp
@@ -46,6 +46,9 @@ void Prisoner::draw() {
}
bool Prisoner::msgKeypress(const KeypressMessage &msg) {
+ if (endDelay())
+ return true;
+
if (msg.keycode < Common::KEYCODE_1 || msg.keycode > Common::KEYCODE_3)
return true;
@@ -55,6 +58,7 @@ bool Prisoner::msgKeypress(const KeypressMessage &msg) {
case Common::KEYCODE_1:
line = STRING["maps.prisoners.flees"];
align = _freeAlignment;
+ g_maps->clearSpecial();
flee();
break;
@@ -78,17 +82,23 @@ bool Prisoner::msgKeypress(const KeypressMessage &msg) {
}
}
- findView("GameParty")->redraw();
if (align != NEUTRAL) {
clearSurface();
writeString(0, 1, line);
Sound::sound(SOUND_2);
+ delaySeconds(3);
+
+ } else {
+ close();
}
- close();
return true;
}
+void Prisoner::timeout() {
+ close();
+}
+
/*------------------------------------------------------------------------*/
ChildPrisoner::ChildPrisoner() :
@@ -124,7 +134,6 @@ MaidenPrisoner::MaidenPrisoner() :
void MaidenPrisoner::flee() {
MM1::Maps::Map &map = *g_maps->_currentMap;
map._walls[48] &= 0x7f;
- g_maps->clearSpecial();
}
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/prisoners.h b/engines/mm/mm1/views/maps/prisoners.h
index 4a0d1a1f5a3..12f89bd827c 100644
--- a/engines/mm/mm1/views/maps/prisoners.h
+++ b/engines/mm/mm1/views/maps/prisoners.h
@@ -45,6 +45,7 @@ public:
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
+ void timeout() override;
};
class ChildPrisoner : public Prisoner {
Commit: 185af7877c1cf326bfc0109e37a81aa381a972e4
https://github.com/scummvm/scummvm/commit/185af7877c1cf326bfc0109e37a81aa381a972e4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Fixes for searching, and trap triggering in it
Changed paths:
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/trap.cpp
engines/mm/mm1/views/trap.h
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 7e2034073e4..38a89e8ce49 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -29,7 +29,7 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 142
+#define TREASURE_STATE 142
static const byte MATCH_ITEMS[7] = {
0, 0, MAP_OF_DESERT_ID, 0, 0, 0, 0
@@ -66,7 +66,7 @@ void Map43::special00() {
}
void Map43::special01() {
- _data[VAL1] = 0;
+ _data[TREASURE_STATE] = 0;
if (g_maps->_forwardMask == DIRMASK_E) {
visitedExit();
@@ -117,13 +117,13 @@ void Map43::special05() {
}
void Map43::special06() {
- if (_data[VAL1]) {
+ if (_data[TREASURE_STATE]) {
g_globals->_treasure.setGold(18000);
g_maps->clearSpecial();
g_events->addAction(KEYBIND_SEARCH);
} else {
Game::Encounter &enc = g_globals->_encounters;
- _data[VAL1]++;
+ _data[TREASURE_STATE]++;
enc.clearMonsters();
for (int i = 0; i < 8; ++i)
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index b39af3b0274..5913f9d0928 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -97,6 +97,15 @@ void Search::draw() {
drawItem();
break;
+ case WHO_WILL_TRY: {
+ line = Common::String::format(
+ STRING["dialogs.search.who_will_try"].c_str(),
+ '0' + g_globals->_party.size()
+ );
+ writeString(10, 1, line);
+ break;
+ }
+
default:
break;
}
@@ -230,6 +239,7 @@ void Search::openContainer2() {
if (getRandomNumber(thresold + 5) < thresold) {
// Triggered a trap
+ _mode = FOCUS_GET_TREASURE;
g_events->send("Trap", GameMessage("TRAP"));
return;
}
@@ -308,11 +318,6 @@ void Search::getTreasure() {
int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 3 : 1;
send("View", DrawGraphicMessage(gfxNum + 65));
- uint gems = g_globals->_treasure.getGems();
- if (gems) {
-
- }
-
draw();
}
@@ -328,7 +333,7 @@ void Search::drawTreasure() {
Character &c = g_globals->_party[i];
uint32 newGold = c._gold + goldPerPerson;
if (newGold < c._gold)
- // As unlikely as it to overflow 32-bits
+ // As unlikely as it is to overflow 32-bits
newGold = 0xffffffff;
c._gold = newGold;
}
diff --git a/engines/mm/mm1/views/trap.cpp b/engines/mm/mm1/views/trap.cpp
index ff43948fc4d..c193d45e710 100644
--- a/engines/mm/mm1/views/trap.cpp
+++ b/engines/mm/mm1/views/trap.cpp
@@ -42,6 +42,7 @@ bool Trap::msgGame(const GameMessage &msg) {
return true;
} else if (msg._name == "TRAP") {
+ open();
trap();
return true;
}
@@ -52,26 +53,29 @@ bool Trap::msgGame(const GameMessage &msg) {
void Trap::draw() {
clearSurface();
- writeString(9, 1, STRING["dialogs.trap.oops"]);
- delaySeconds(3);
+ if (_mode == MODE_TRIGGER) {
+ writeString(9, 1, STRING["dialogs.trap.oops"]);
+ } else {
+ writeString(0, 1,
+ STRING[Common::String::format("dialogs.trap.%d", _trapType)]);
+ }
}
bool Trap::msgKeypress(const KeypressMessage &msg) {
- endDelay();
- return true;
-}
-
-void Trap::timeout() {
- if (isFocused())
+ if (_mode == MODE_TRIGGER) {
+ trap();
+ } else {
close();
- trap();
+ }
+
+ return true;
}
void Trap::trap() {
TrapData::trap();
- send(InfoMessage(0, 1,
- STRING[Common::String::format("dialogs.trap.%d", _trapType)]));
+ _mode = MODE_TRAP;
+ draw();
}
} // namespace Views
diff --git a/engines/mm/mm1/views/trap.h b/engines/mm/mm1/views/trap.h
index d4268166d90..48d6ce364f1 100644
--- a/engines/mm/mm1/views/trap.h
+++ b/engines/mm/mm1/views/trap.h
@@ -30,6 +30,9 @@ namespace MM1 {
namespace Views {
class Trap : public TextView, public TrapData {
+private:
+ enum Mode { MODE_TRIGGER, MODE_TRAP };
+ Mode _mode = MODE_TRIGGER;
protected:
void trap() override;
@@ -40,7 +43,6 @@ public:
bool msgGame(const GameMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
- void timeout() override;
};
} // namespace Views
Commit: 7b1d6e6f5b390556f26cc9e30bdfc1ce45bb73ff
https://github.com/scummvm/scummvm/commit/7b1d6e6f5b390556f26cc9e30bdfc1ce45bb73ff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Remove search debugging line
Changed paths:
engines/mm/mm1/views/game.cpp
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 1e1f68fd5f5..5779ef8723f 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -67,7 +67,6 @@ bool Game::msgAction(const ActionMessage &msg) {
g_events->send(GameMessage("REST"));
return true;
case KEYBIND_SEARCH:
- g_globals->_treasure._items[2] = 240; //***DEBUG***
send("Search", GameMessage("SHOW"));
break;
case KEYBIND_UNLOCK:
Commit: 3ca92a0b1b7a52da46b8d440efc000e068f71761
https://github.com/scummvm/scummvm/commit/3ca92a0b1b7a52da46b8d440efc000e068f71761
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Fix checking into inns
Changed paths:
engines/mm/mm1/data/roster.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/views/locations/inn.cpp
diff --git a/engines/mm/mm1/data/roster.cpp b/engines/mm/mm1/data/roster.cpp
index b51438ccc3f..1a8a53d54a0 100644
--- a/engines/mm/mm1/data/roster.cpp
+++ b/engines/mm/mm1/data/roster.cpp
@@ -77,7 +77,7 @@ void Roster::update(const IntArray &charNums) {
} else {
for (destIndex = 0; destIndex < ROSTER_COUNT; ++destIndex) {
- if (_items[destIndex]._name == c._name)
+ if (!strcmp(_items[destIndex]._name, c._name))
break;
}
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index b6e14ce5123..91550c65f5d 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -190,6 +190,13 @@ public:
return g_events->send(name, msg);
}
+ /**
+ * Returns the map's index
+ */
+ uint getMapIndex() const {
+ return _mapIndex;
+ }
+
/**
* Updates the game display
*/
diff --git a/engines/mm/mm1/views/locations/inn.cpp b/engines/mm/mm1/views/locations/inn.cpp
index 5ef2a964f81..c3c44e9f79e 100644
--- a/engines/mm/mm1/views/locations/inn.cpp
+++ b/engines/mm/mm1/views/locations/inn.cpp
@@ -28,6 +28,10 @@ namespace Views {
namespace Locations {
bool Inn::msgFocus(const FocusMessage &msg) {
+ if (g_maps->_currentMap)
+ // Update the starting town
+ g_globals->_startingTown = (Maps::TownId)g_maps->_currentMap->dataByte(Maps::MAP_ID);
+
// Save the roster
g_globals->_roster.update(_partyChars);
g_globals->_roster.save();
Commit: 33b138d3b5b991454cf86ff62e778639902690f9
https://github.com/scummvm/scummvm/commit/33b138d3b5b991454cf86ff62e778639902690f9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:44+01:00
Commit Message:
MM: MM1: Map 1 fixes
Changed paths:
engines/mm/mm1/maps/map01.cpp
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index fe7cd528310..6f5b05e6bc2 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -116,13 +116,12 @@ void Map01::special08() {
c._condition = PARALYZED;
}
- // Redraw the party
- g_events->send("GameParty", GameMessage("UPDATE"));
-
+ redrawGame();
+
// Show the message and wait for a keypress
send(SoundMessage(
STRING["maps.map01.secret"],
- []() {
+ [](const Common::KeyState &) {
Game::Encounter &enc = g_globals->_encounters;
enc.clearMonsters();
@@ -141,7 +140,7 @@ void Map01::special08() {
void Map01::special09() {
visitedExit();
send(SoundMessage(
- STRING["maps.map01.passage_outside"],
+ STRING["maps.stairs_down"],
[]() {
g_maps->_mapPos = Common::Point(8, 0);
g_maps->changeMap(0xc01, 1);
@@ -167,7 +166,7 @@ void Map01::special13() {
void Map01::special14() {
send(SoundMessage(
- 0, 1, STRING["maps.map00.zam0"]
+ 0, 1, STRING["maps.map01.zam0"]
));
}
Commit: 66c994f8dba6bc4ffd7a99dafa8ed81418d9e897
https://github.com/scummvm/scummvm/commit/66c994f8dba6bc4ffd7a99dafa8ed81418d9e897
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Fix colors for map 19
Changed paths:
engines/mm/mm1/maps/maps.cpp
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 13785a89507..d78c6642b67 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -121,7 +121,7 @@ static const uint16 TILE_HEIGHTS[RESOURCE_TILES_COUNT] = {
static byte TILE_COLORS[18] = {
0xe6, 0xe6, 0xe6, 0x72, 0x72, 0x72, 0x62, 0x62, 0x62,
- 0x62, 0x62, 0xe1, 0, 0, 0, 0x43, 0x43, 0x63
+ 0x62, 0x62, 0xe1, 0x53, 0x53, 0xff, 0x43, 0x43, 0x63
};
Maps::Maps() {
Commit: 4a5b21f1a1a19ba8d4248c782e35270a55d24a3d
https://github.com/scummvm/scummvm/commit/4a5b21f1a1a19ba8d4248c782e35270a55d24a3d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Fixes for Ice Princess
Changed paths:
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/views/game.cpp
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/maps/ice_princess.cpp
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index b0696c376ff..c06bf265c3a 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -101,7 +101,7 @@ void Map::updateGame() {
}
void Map::redrawGame() {
- g_events->findView("Game")->redraw();
+ g_events->send("Game", GameMessage("REDRAW"));
}
void Map::encounter(const byte *id1, const byte *id2) {
diff --git a/engines/mm/mm1/views/game.cpp b/engines/mm/mm1/views/game.cpp
index 5779ef8723f..9be40cd7cd5 100644
--- a/engines/mm/mm1/views/game.cpp
+++ b/engines/mm/mm1/views/game.cpp
@@ -96,6 +96,9 @@ bool Game::msgGame(const GameMessage &msg) {
if (msg._name == "DISPLAY") {
replaceView(this);
return true;
+ } else if (msg._name == "REDRAW") {
+ redraw();
+ g_events->drawElements();
}
return TextView::msgGame(msg);
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 29ccc6e6a9d..7b1b69a66fb 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -52,6 +52,9 @@ void GameMessages::draw() {
}
bool GameMessages::msgInfo(const InfoMessage &msg) {
+ // Refresh the underlying screen first
+ g_events->send("Game", GameMessage("REDRAW"));
+
if (msg._ynCallback || msg._keyCallback ||
g_globals->_party.isPartyDead()) {
addView(this);
diff --git a/engines/mm/mm1/views/maps/ice_princess.cpp b/engines/mm/mm1/views/maps/ice_princess.cpp
index 488afd827a8..23730770f89 100644
--- a/engines/mm/mm1/views/maps/ice_princess.cpp
+++ b/engines/mm/mm1/views/maps/ice_princess.cpp
@@ -33,7 +33,7 @@ namespace Maps {
#define ANSWER_OFFSET 167
IcePrincess::IcePrincess() :
- AnswerEntry("IcePrincess", Common::Point(9, 5), 10) {
+ AnswerEntry("IcePrincess", Common::Point(9, 7), 10) {
_bounds = getLineBounds(17, 24);
}
@@ -50,7 +50,7 @@ void IcePrincess::answerEntered() {
close();
for (int i = 0; i < 4; ++i)
- properAnswer += (map[ANSWER_OFFSET + i] & 0x7f) - 64;
+ properAnswer += (map[ANSWER_OFFSET + i] & 0x7f) + 64;
if (_answer == properAnswer) {
InfoMessage msg(
Commit: 768352489545a9a2b9388896a98cbb598142271b
https://github.com/scummvm/scummvm/commit/768352489545a9a2b9388896a98cbb598142271b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Add missing access code view
Changed paths:
engines/mm/mm1/views/dialogs.h
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index dba4cbbbba7..19331a9c2ed 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -48,6 +48,7 @@
#include "mm/mm1/views/locations/tavern.h"
#include "mm/mm1/views/locations/temple.h"
#include "mm/mm1/views/locations/training.h"
+#include "mm/mm1/views/maps/access_code.h"
#include "mm/mm1/views/maps/alamar.h"
#include "mm/mm1/views/maps/alien.h"
#include "mm/mm1/views/maps/arrested.h"
@@ -109,6 +110,7 @@ private:
Views::Locations::Temple _temple;
Views::Locations::Training _training;
+ Views::Maps::AccessCode _accessCode;
Views::Maps::Alamar _alamar;
Views::Maps::Alien _alien;
Views::Maps::Arrested _arrested;
Commit: b98e435e34f98b59f788198ac1aa23cec18811c3
https://github.com/scummvm/scummvm/commit/b98e435e34f98b59f788198ac1aa23cec18811c3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Map 13 fixes
Changed paths:
engines/mm/mm1/maps/map13.cpp
engines/mm/mm1/views/search.cpp
engines/mm/mm1/views/text_view.cpp
diff --git a/engines/mm/mm1/maps/map13.cpp b/engines/mm/mm1/maps/map13.cpp
index f012757b2db..c0fe0c835ea 100644
--- a/engines/mm/mm1/maps/map13.cpp
+++ b/engines/mm/mm1/maps/map13.cpp
@@ -89,7 +89,7 @@ void Map13::special00() {
void Map13::special01() {
if (_data[VAL1]) {
g_maps->clearSpecial();
- g_globals->_treasure._items[2] = 246;
+ g_globals->_treasure._items[2] = MEDUSA_HEAD_ID;
g_events->addAction(KEYBIND_SEARCH);
} else {
_data[VAL1]++;
@@ -115,7 +115,7 @@ void Map13::special02() {
c._condition = POISONED;
}
- send(SoundMessage(STRING["maps.map13.pit"]));
+ send(SoundMessage(STRING["maps.map13.snake_pit"]));
}
}
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 5913f9d0928..e93c781234a 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -112,6 +112,9 @@ void Search::draw() {
}
bool Search::msgKeypress(const KeypressMessage &msg) {
+ if (endDelay())
+ return true;
+
switch (_mode) {
case INITIAL:
endDelay();
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index 4d1b54f3aaf..cef8c1b19b6 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -143,9 +143,14 @@ void TextView::timeout() {
}
bool TextView::msgDrawGraphic(const DrawGraphicMessage &msg) {
+ // Refresh the background
+ draw();
+
+ // Draw the new image
const Graphics::ManagedSurface img =
g_globals->_monsters.getMonsterImage(msg._gfxNum);
getSurface().blitFrom(img, Common::Point(64, 16));
+
return true;
}
Commit: c0f6e0773a9ab6794f7f1053dd966ce76080f1e6
https://github.com/scummvm/scummvm/commit/c0f6e0773a9ab6794f7f1053dd966ce76080f1e6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Map 18 fixes
Changed paths:
engines/mm/mm1/events.h
engines/mm/mm1/maps/map18.cpp
engines/mm/mm1/views/game_messages.cpp
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 308e31eced9..fca219678e8 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -149,7 +149,7 @@ public:
* Closes the current view. The view must have been added
* via addView, so there's a remaining view afterwards
*/
- void close();
+ virtual void close();
/*
* Returns true if the view is focused
@@ -361,6 +361,13 @@ public:
bool tick() override {
return !_views.empty() ? focusedView()->tick() : false;
}
+
+ /**
+ * Calling the close method for g_events closes the active window
+ */
+ void close() override {
+ focusedView()->close();
+ }
};
extern Events *g_events;
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index 25188fedd96..ad5eb1bce15 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -69,21 +69,23 @@ void Map18::special01() {
g_maps->_mapPos = Common::Point(0, 7);
g_maps->changeMap(0x508, 3);
- } else if (_data[VAL1] == 0) {
+ } else if (_data[VAL1] != 0) {
_data[VAL1] = 0;
} else {
- redrawGame();
+ send("View", DrawGraphicMessage(65 + 6));
send(SoundMessage(
- STRING["maps.map18.blackridge_south"],
+ STRING["maps.map18.castle_south"],
[](const Common::KeyState &ks) {
Map18 &map = *static_cast<Map18 *>(g_maps->_currentMap);
if (ks.keycode == Common::KEYCODE_y) {
g_events->close();
map[VAL1] = 0xff;
+ map.updateGame();
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->close();
map[VAL1]++;
+ map.updateGame();
}
}
));
@@ -96,21 +98,23 @@ void Map18::special02() {
g_maps->_mapPos = Common::Point(7, 15);
g_maps->changeMap(0xf08, 3);
- } else if (_data[VAL1] == 0) {
+ } else if (_data[VAL2] != 0) {
_data[VAL2] = 0;
} else {
- redrawGame();
+ send("View", DrawGraphicMessage(65 + 6));
send(SoundMessage(
- STRING["maps.map18.blackridge_north"],
+ STRING["maps.map18.castle_north"],
[](const Common::KeyState &ks) {
Map18 &map = *static_cast<Map18 *>(g_maps->_currentMap);
if (ks.keycode == Common::KEYCODE_y) {
g_events->close();
map[VAL2] = 0xff;
+ map.updateGame();
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->close();
map[VAL2]++;
+ map.updateGame();
}
}
));
@@ -168,7 +172,7 @@ void Map18::special08() {
void Map18::special09() {
g_maps->clearSpecial();
- g_globals->_treasure._items[2] = 238;
+ g_globals->_treasure._items[2] = SILVER_KEY_ID;
g_globals->_treasure._trapType = 4;
g_globals->_treasure._container = IRON_BOX;
g_globals->_treasure.setGold(2400);
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 7b1b69a66fb..29ccc6e6a9d 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -52,9 +52,6 @@ void GameMessages::draw() {
}
bool GameMessages::msgInfo(const InfoMessage &msg) {
- // Refresh the underlying screen first
- g_events->send("Game", GameMessage("REDRAW"));
-
if (msg._ynCallback || msg._keyCallback ||
g_globals->_party.isPartyDead()) {
addView(this);
Commit: bae79d8206cfbb428d2c6557929220d09bcac60f
https://github.com/scummvm/scummvm/commit/bae79d8206cfbb428d2c6557929220d09bcac60f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Prevent old text showing when going from large messages to normal
Changed paths:
engines/mm/mm1/views/game_messages.cpp
engines/mm/mm1/views/game_messages.h
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index 29ccc6e6a9d..d1ea2612937 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -33,6 +33,11 @@ GameMessages::GameMessages(UIElement *owner) :
_bounds = getLineBounds(21, 24);
}
+bool GameMessages::msgUnfocus(const UnfocusMessage &msg) {
+ clearSurface();
+ return true;
+}
+
void GameMessages::draw() {
clearSurface();
diff --git a/engines/mm/mm1/views/game_messages.h b/engines/mm/mm1/views/game_messages.h
index 791b5848be1..32c1e94ce48 100644
--- a/engines/mm/mm1/views/game_messages.h
+++ b/engines/mm/mm1/views/game_messages.h
@@ -38,6 +38,7 @@ public:
GameMessages(UIElement *owner);
virtual ~GameMessages() {}
+ bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgInfo(const InfoMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
Commit: b8852e1df43e6f839757d74141a60775ce8e1dfa
https://github.com/scummvm/scummvm/commit/b8852e1df43e6f839757d74141a60775ce8e1dfa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Added a default section to every map
This will be used by the console to make it easier
to switch to arbitrary maps without having to figure
out the section each time
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map00.h
engines/mm/mm1/maps/map01.h
engines/mm/mm1/maps/map02.h
engines/mm/mm1/maps/map03.h
engines/mm/mm1/maps/map04.h
engines/mm/mm1/maps/map05.h
engines/mm/mm1/maps/map06.h
engines/mm/mm1/maps/map07.h
engines/mm/mm1/maps/map08.h
engines/mm/mm1/maps/map09.h
engines/mm/mm1/maps/map10.h
engines/mm/mm1/maps/map11.h
engines/mm/mm1/maps/map12.h
engines/mm/mm1/maps/map13.h
engines/mm/mm1/maps/map14.h
engines/mm/mm1/maps/map15.h
engines/mm/mm1/maps/map16.h
engines/mm/mm1/maps/map17.h
engines/mm/mm1/maps/map18.h
engines/mm/mm1/maps/map19.h
engines/mm/mm1/maps/map20.h
engines/mm/mm1/maps/map21.h
engines/mm/mm1/maps/map22.h
engines/mm/mm1/maps/map23.h
engines/mm/mm1/maps/map24.h
engines/mm/mm1/maps/map25.h
engines/mm/mm1/maps/map26.h
engines/mm/mm1/maps/map27.h
engines/mm/mm1/maps/map28.h
engines/mm/mm1/maps/map29.h
engines/mm/mm1/maps/map30.h
engines/mm/mm1/maps/map31.h
engines/mm/mm1/maps/map32.h
engines/mm/mm1/maps/map33.h
engines/mm/mm1/maps/map34.h
engines/mm/mm1/maps/map35.h
engines/mm/mm1/maps/map36.h
engines/mm/mm1/maps/map37.h
engines/mm/mm1/maps/map38.h
engines/mm/mm1/maps/map39.h
engines/mm/mm1/maps/map40.h
engines/mm/mm1/maps/map41.h
engines/mm/mm1/maps/map42.h
engines/mm/mm1/maps/map43.h
engines/mm/mm1/maps/map44.h
engines/mm/mm1/maps/map45.h
engines/mm/mm1/maps/map46.h
engines/mm/mm1/maps/map47.h
engines/mm/mm1/maps/map48.h
engines/mm/mm1/maps/map49.h
engines/mm/mm1/maps/map50.h
engines/mm/mm1/maps/map51.h
engines/mm/mm1/maps/map52.h
engines/mm/mm1/maps/map53.h
engines/mm/mm1/maps/map54.h
engines/mm/mm1/maps/map_desert.h
engines/mm/mm1/maps/map_town.h
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 20e5f7868fd..7700c200c6a 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -248,20 +248,23 @@ bool Console::cmdMapString(int argc, const char **argv) {
}
bool Console::cmdMap(int argc, const char **argv) {
- if (argc < 2) {
+ if (argc != 2 && argc != 4) {
debugPrintf("map mapId [ xp, yp ]\n");
return true;
} else {
Maps::Maps &maps = g_globals->_maps;
-
int mapId = strToInt(argv[1]);
- int x = argc < 3 ? 8 : strToInt(argv[2]);
- int y = argc < 4 ? 8 : strToInt(argv[3]);
+ Maps::Map &map = *maps.getMap(mapId);
+ int x = g_maps->_mapPos.x, y = g_maps->_mapPos.y;
+
+ if (argc == 4) {
+ x = strToInt(argv[2]);
+ y = strToInt(argv[3]);
+ }
- maps.select(maps.getMap(mapId)->getId(), 0);
maps._mapPos.x = x;
maps._mapPos.y = y;
- g_events->send("Game", GameMessage("UPDATE"));
+ maps.changeMap(map.getId(), map.getDefaultSection());
return false;
}
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index c06bf265c3a..f3120b108ab 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -29,8 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
-Map::Map(uint index, const Common::String &name, uint16 id) :
- _mapIndex(index), _name(name), _id(id) {
+Map::Map(uint index, const Common::String &name, uint16 id, byte defaultSection) :
+ _mapIndex(index), _name(name), _id(id), _defaultSection(defaultSection) {
Common::fill((byte *)&_walls[0], (byte *)&_walls[MAP_SIZE], 0);
Common::fill(&_states[0], (byte *)&_states[MAP_SIZE], 0);
Common::fill(&_visited[0], &_visited[MAP_SIZE], 0);
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 91550c65f5d..178926179e4 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -99,6 +99,7 @@ protected:
Common::String _name;
uint16 _id;
uint _mapIndex;
+ byte _defaultSection;
Common::Array<byte> _data;
private:
/**
@@ -134,7 +135,8 @@ public:
byte _states[MAP_SIZE];
uint8 _visited[MAP_SIZE];
public:
- Map(uint index, const Common::String &name, uint16 id);
+ Map(uint index, const Common::String &name, uint16 id,
+ byte defaultSection);
virtual ~Map() {}
/**
@@ -157,6 +159,13 @@ public:
*/
uint16 getId() const { return _id; }
+ /**
+ * Returns the map default section
+ */
+ byte getDefaultSection() const {
+ return _defaultSection;
+ }
+
/**
* Accesses the map data
*/
diff --git a/engines/mm/mm1/maps/map00.h b/engines/mm/mm1/maps/map00.h
index e41e9c057ce..f741676f2dc 100644
--- a/engines/mm/mm1/maps/map00.h
+++ b/engines/mm/mm1/maps/map00.h
@@ -85,7 +85,7 @@ private:
&Map00::special23
};
public:
- Map00() : MapTown(0, "sorpigal", 0x604) {}
+ Map00() : MapTown(0, "sorpigal", 0x604, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map01.h b/engines/mm/mm1/maps/map01.h
index d9b3a93b883..bc0c302a310 100644
--- a/engines/mm/mm1/maps/map01.h
+++ b/engines/mm/mm1/maps/map01.h
@@ -69,7 +69,7 @@ private:
&Map01::special16
};
public:
- Map01() : MapTown(1, "portsmit", 0xC03) {}
+ Map01() : MapTown(1, "portsmit", 0xc03, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map02.h b/engines/mm/mm1/maps/map02.h
index 33ca57f6f55..2d48e471a44 100644
--- a/engines/mm/mm1/maps/map02.h
+++ b/engines/mm/mm1/maps/map02.h
@@ -76,7 +76,7 @@ private:
&Map02::special21
};
public:
- Map02() : MapTown(2, "algary", 0x203) {}
+ Map02() : MapTown(2, "algary", 0x203, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map03.h b/engines/mm/mm1/maps/map03.h
index ce83e458729..c084a7b192e 100644
--- a/engines/mm/mm1/maps/map03.h
+++ b/engines/mm/mm1/maps/map03.h
@@ -85,7 +85,7 @@ private:
&Map03::special28
};
public:
- Map03() : MapTown(3, "dusk", 0x802) {}
+ Map03() : MapTown(3, "dusk", 0x802, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map04.h b/engines/mm/mm1/maps/map04.h
index b52627f238a..ca16d7bf536 100644
--- a/engines/mm/mm1/maps/map04.h
+++ b/engines/mm/mm1/maps/map04.h
@@ -77,7 +77,7 @@ private:
&Map04::special21
};
public:
- Map04() : MapTown(4, "erliquin", 0x0B1A) {}
+ Map04() : MapTown(4, "erliquin", 0xb1a, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map05.h b/engines/mm/mm1/maps/map05.h
index 808a7e15d84..14c35516e84 100644
--- a/engines/mm/mm1/maps/map05.h
+++ b/engines/mm/mm1/maps/map05.h
@@ -75,7 +75,7 @@ private:
&Map05::special08
};
public:
- Map05() : Map(5, "cave1", 0x0A11) {}
+ Map05() : Map(5, "cave1", 0xa11, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map06.h b/engines/mm/mm1/maps/map06.h
index 45155dc0476..4967e48cb27 100644
--- a/engines/mm/mm1/maps/map06.h
+++ b/engines/mm/mm1/maps/map06.h
@@ -74,7 +74,7 @@ private:
&Map06::special26
};
public:
- Map06() : Map(6, "cave2", 0x1) {}
+ Map06() : Map(6, "cave2", 0x1, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map07.h b/engines/mm/mm1/maps/map07.h
index f2b794c2341..853b1cdaa98 100644
--- a/engines/mm/mm1/maps/map07.h
+++ b/engines/mm/mm1/maps/map07.h
@@ -71,7 +71,7 @@ private:
&Map07::special17
};
public:
- Map07() : Map(7, "cave3", 0xC01) {}
+ Map07() : Map(7, "cave3", 0xC01, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map08.h b/engines/mm/mm1/maps/map08.h
index a5f732717ba..d91b350026d 100644
--- a/engines/mm/mm1/maps/map08.h
+++ b/engines/mm/mm1/maps/map08.h
@@ -68,7 +68,7 @@ private:
&Map08::special20
};
public:
- Map08() : Map(8, "cave4", 0x202) {}
+ Map08() : Map(8, "cave4", 0x202, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map09.h b/engines/mm/mm1/maps/map09.h
index 7cc4e09473c..18754486740 100644
--- a/engines/mm/mm1/maps/map09.h
+++ b/engines/mm/mm1/maps/map09.h
@@ -81,7 +81,7 @@ private:
&Map09::special27
};
public:
- Map09() : Map(9, "cave5", 0x5) {}
+ Map09() : Map(9, "cave5", 0x5, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map10.h b/engines/mm/mm1/maps/map10.h
index 5d3a554624e..9071f2cfcb6 100644
--- a/engines/mm/mm1/maps/map10.h
+++ b/engines/mm/mm1/maps/map10.h
@@ -82,7 +82,7 @@ private:
&Map10::special33
};
public:
- Map10() : Map(10, "cave6", 0x51B) {}
+ Map10() : Map(10, "cave6", 0x51b, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map11.h b/engines/mm/mm1/maps/map11.h
index 37144a2c144..189f44ee753 100644
--- a/engines/mm/mm1/maps/map11.h
+++ b/engines/mm/mm1/maps/map11.h
@@ -62,7 +62,7 @@ private:
&Map11::special02
};
public:
- Map11() : Map(11, "cave7", 0x212) {}
+ Map11() : Map(11, "cave7", 0x212, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map12.h b/engines/mm/mm1/maps/map12.h
index f9306820321..5ccc29aacf1 100644
--- a/engines/mm/mm1/maps/map12.h
+++ b/engines/mm/mm1/maps/map12.h
@@ -75,7 +75,7 @@ private:
&Map12::special17
};
public:
- Map12() : Map(12, "cave8", 0x601) {}
+ Map12() : Map(12, "cave8", 0x601, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map13.h b/engines/mm/mm1/maps/map13.h
index 676115bdc0b..1f257fd3eca 100644
--- a/engines/mm/mm1/maps/map13.h
+++ b/engines/mm/mm1/maps/map13.h
@@ -65,7 +65,7 @@ private:
&Map13::special22
};
public:
- Map13() : Map(13, "cave9", 0xA00) {}
+ Map13() : Map(13, "cave9", 0xa00, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map14.h b/engines/mm/mm1/maps/map14.h
index 47528713e64..fe1225386c1 100644
--- a/engines/mm/mm1/maps/map14.h
+++ b/engines/mm/mm1/maps/map14.h
@@ -47,7 +47,7 @@ private:
&Map14::special05
};
public:
- Map14() : Map(14, "areaa1", 0xF01) {}
+ Map14() : Map(14, "areaa1", 0xf01, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map15.h b/engines/mm/mm1/maps/map15.h
index 228f5a4d788..1e3ed920f15 100644
--- a/engines/mm/mm1/maps/map15.h
+++ b/engines/mm/mm1/maps/map15.h
@@ -53,7 +53,7 @@ private:
&Map15::special08
};
public:
- Map15() : Map(15, "areaa2", 0x502) {}
+ Map15() : Map(15, "areaa2", 0x502, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map16.h b/engines/mm/mm1/maps/map16.h
index c0230428983..3b8f1e88b9f 100644
--- a/engines/mm/mm1/maps/map16.h
+++ b/engines/mm/mm1/maps/map16.h
@@ -47,7 +47,7 @@ private:
&Map16::special03
};
public:
- Map16() : Map(16, "areaa3", 0xB02) {}
+ Map16() : Map(16, "areaa3", 0xb02, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map17.h b/engines/mm/mm1/maps/map17.h
index 79bbcf5ebc3..dccf5b448d1 100644
--- a/engines/mm/mm1/maps/map17.h
+++ b/engines/mm/mm1/maps/map17.h
@@ -48,7 +48,7 @@ private:
&Map17::special03
};
public:
- Map17() : Map(17, "areaa4", 0x103) {}
+ Map17() : Map(17, "areaa4", 0x103, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map18.h b/engines/mm/mm1/maps/map18.h
index d8ef1609ed5..202d7209a29 100644
--- a/engines/mm/mm1/maps/map18.h
+++ b/engines/mm/mm1/maps/map18.h
@@ -55,7 +55,7 @@ private:
&Map18::special09
};
public:
- Map18() : Map(18, "areab1", 0xA00) {}
+ Map18() : Map(18, "areab1", 0xa00, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map19.h b/engines/mm/mm1/maps/map19.h
index 87db7550a1a..a3fa999b2af 100644
--- a/engines/mm/mm1/maps/map19.h
+++ b/engines/mm/mm1/maps/map19.h
@@ -48,7 +48,7 @@ private:
&Map19::special05
};
public:
- Map19() : Map(19, "areab2", 0x703) {}
+ Map19() : Map(19, "areab2", 0x703, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map20.h b/engines/mm/mm1/maps/map20.h
index 72f3a262731..2087daa477b 100644
--- a/engines/mm/mm1/maps/map20.h
+++ b/engines/mm/mm1/maps/map20.h
@@ -53,7 +53,7 @@ private:
&Map20::special08
};
public:
- Map20() : Map(20, "areab3", 0x101) {}
+ Map20() : Map(20, "areab3", 0x101, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map21.h b/engines/mm/mm1/maps/map21.h
index 9d8e6c69a71..29fb21f4dfc 100644
--- a/engines/mm/mm1/maps/map21.h
+++ b/engines/mm/mm1/maps/map21.h
@@ -48,7 +48,7 @@ private:
&Map21::special04
};
public:
- Map21() : Map(21, "areab4", 0xD03) {}
+ Map21() : Map(21, "areab4", 0xd03, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map22.h b/engines/mm/mm1/maps/map22.h
index 94453ccc86d..4b0efc56a01 100644
--- a/engines/mm/mm1/maps/map22.h
+++ b/engines/mm/mm1/maps/map22.h
@@ -53,7 +53,7 @@ private:
&Map22::special08
};
public:
- Map22() : Map(22, "areac1", 0x304) {}
+ Map22() : Map(22, "areac1", 0x304, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map23.h b/engines/mm/mm1/maps/map23.h
index d455c723ced..7036e3491b8 100644
--- a/engines/mm/mm1/maps/map23.h
+++ b/engines/mm/mm1/maps/map23.h
@@ -60,7 +60,7 @@ private:
&Map23::special13
};
public:
- Map23() : Map(23, "areac2", 0xA11) {}
+ Map23() : Map(23, "areac2", 0xa11, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map24.h b/engines/mm/mm1/maps/map24.h
index b35ad96bc65..d59bf2d5e76 100644
--- a/engines/mm/mm1/maps/map24.h
+++ b/engines/mm/mm1/maps/map24.h
@@ -51,7 +51,7 @@ private:
&Map24::special09
};
public:
- Map24() : Map(24, "areac3", 0x904) {}
+ Map24() : Map(24, "areac3", 0x904, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map25.h b/engines/mm/mm1/maps/map25.h
index 2d44a526a2a..d8cf73360cf 100644
--- a/engines/mm/mm1/maps/map25.h
+++ b/engines/mm/mm1/maps/map25.h
@@ -42,7 +42,7 @@ private:
&Map25::special02
};
public:
- Map25() : Map(25, "areac4", 0xF04) {}
+ Map25() : Map(25, "areac4", 0xf04, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map26.h b/engines/mm/mm1/maps/map26.h
index 1c6729f4ca4..acf26dee6c6 100644
--- a/engines/mm/mm1/maps/map26.h
+++ b/engines/mm/mm1/maps/map26.h
@@ -44,7 +44,7 @@ private:
&Map26::special03
};
public:
- Map26() : MapDesert(26, "aread1", 0x505,
+ Map26() : MapDesert(26, "aread1", 0x505, 2,
_data[247], MapDesert::RND_FULL) {}
/**
diff --git a/engines/mm/mm1/maps/map27.h b/engines/mm/mm1/maps/map27.h
index 9f45bd73247..700e4d3064c 100644
--- a/engines/mm/mm1/maps/map27.h
+++ b/engines/mm/mm1/maps/map27.h
@@ -48,7 +48,7 @@ private:
&Map27::special05
};
public:
- Map27() : MapDesert(27, "aread2", 0xB05,
+ Map27() : MapDesert(27, "aread2", 0xb05, 2,
_data[66], MapDesert::RND_BASIC) {}
/**
diff --git a/engines/mm/mm1/maps/map28.h b/engines/mm/mm1/maps/map28.h
index 7697b4f38b2..4fb89087448 100644
--- a/engines/mm/mm1/maps/map28.h
+++ b/engines/mm/mm1/maps/map28.h
@@ -43,7 +43,7 @@ private:
&Map28::special02
};
public:
- Map28() : Map(28, "aread3", 0x106) {}
+ Map28() : Map(28, "aread3", 0x106, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map29.h b/engines/mm/mm1/maps/map29.h
index 6e46ef5a3ec..1d1273d9e9a 100644
--- a/engines/mm/mm1/maps/map29.h
+++ b/engines/mm/mm1/maps/map29.h
@@ -43,7 +43,7 @@ private:
&Map29::special03
};
public:
- Map29() : Map(29, "aread4", 0x801) {}
+ Map29() : Map(29, "aread4", 0x801, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map30.h b/engines/mm/mm1/maps/map30.h
index 56fa0025e8c..1b3d2b5f625 100644
--- a/engines/mm/mm1/maps/map30.h
+++ b/engines/mm/mm1/maps/map30.h
@@ -43,7 +43,7 @@ private:
&Map30::special03
};
public:
- Map30() : MapDesert(30, "areae1", 0x112,
+ Map30() : MapDesert(30, "areae1", 0x112, 2,
_data[137], MapDesert::RND_FULL) {}
/**
diff --git a/engines/mm/mm1/maps/map31.h b/engines/mm/mm1/maps/map31.h
index a74acd67524..29ec133ce2a 100644
--- a/engines/mm/mm1/maps/map31.h
+++ b/engines/mm/mm1/maps/map31.h
@@ -46,7 +46,7 @@ private:
&Map31::special06
};
public:
- Map31() : MapDesert(31, "areae2", 0x706, _data[80],
+ Map31() : MapDesert(31, "areae2", 0x706, 3, _data[80],
MapDesert::RND_BASIC) {}
/**
diff --git a/engines/mm/mm1/maps/map32.h b/engines/mm/mm1/maps/map32.h
index a0a73b6d0d1..b5e007e0c5b 100644
--- a/engines/mm/mm1/maps/map32.h
+++ b/engines/mm/mm1/maps/map32.h
@@ -46,7 +46,7 @@ private:
&Map32::special05
};
public:
- Map32() : Map(32, "areae3", 0xB1A) {}
+ Map32() : Map(32, "areae3", 0xb1a, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map33.h b/engines/mm/mm1/maps/map33.h
index 5edf111aa89..7d26aebd752 100644
--- a/engines/mm/mm1/maps/map33.h
+++ b/engines/mm/mm1/maps/map33.h
@@ -46,7 +46,7 @@ private:
&Map33::special04
};
public:
- Map33() : Map(33, "areae4", 0x11B) {}
+ Map33() : Map(33, "areae4", 0x11b, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map34.h b/engines/mm/mm1/maps/map34.h
index f879c01b60b..12d628b5caf 100644
--- a/engines/mm/mm1/maps/map34.h
+++ b/engines/mm/mm1/maps/map34.h
@@ -77,7 +77,7 @@ private:
&Map34::special01
};
public:
- Map34() : Map(34, "doom", 0x706) {}
+ Map34() : Map(34, "doom", 0x706, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map35.h b/engines/mm/mm1/maps/map35.h
index 2508adbebd6..9d5e409e8f8 100644
--- a/engines/mm/mm1/maps/map35.h
+++ b/engines/mm/mm1/maps/map35.h
@@ -56,7 +56,7 @@ private:
&Map35::special09
};
public:
- Map35() : Map(35, "blackrn", 0xF08) {}
+ Map35() : Map(35, "blackrn", 0xf08, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map36.h b/engines/mm/mm1/maps/map36.h
index ba5689723e2..52a17520bc0 100644
--- a/engines/mm/mm1/maps/map36.h
+++ b/engines/mm/mm1/maps/map36.h
@@ -61,7 +61,7 @@ private:
&Map36::special11
};
public:
- Map36() : Map(36, "blackrs", 0x508) {}
+ Map36() : Map(36, "blackrs", 0x508, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map37.h b/engines/mm/mm1/maps/map37.h
index ab8ef7681e6..cb7d3e378e0 100644
--- a/engines/mm/mm1/maps/map37.h
+++ b/engines/mm/mm1/maps/map37.h
@@ -73,7 +73,7 @@ private:
&Map37::special19
};
public:
- Map37() : Map(37, "qvl1", 0xF03) {}
+ Map37() : Map(37, "qvl1", 0xf03, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map38.h b/engines/mm/mm1/maps/map38.h
index eaa0c851699..b52accf79dd 100644
--- a/engines/mm/mm1/maps/map38.h
+++ b/engines/mm/mm1/maps/map38.h
@@ -73,7 +73,7 @@ private:
&Map38::special18
};
public:
- Map38() : Map(38, "qvl2", 0x703) {}
+ Map38() : Map(38, "qvl2", 0x703, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map39.h b/engines/mm/mm1/maps/map39.h
index cee44c8a720..66892d4cf9b 100644
--- a/engines/mm/mm1/maps/map39.h
+++ b/engines/mm/mm1/maps/map39.h
@@ -70,7 +70,7 @@ private:
&Map39::special18
};
public:
- Map39() : Map(39, "rwl1", 0xF02) {}
+ Map39() : Map(39, "rwl1", 0xf02, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map40.h b/engines/mm/mm1/maps/map40.h
index d24deba9f13..f404755ab25 100644
--- a/engines/mm/mm1/maps/map40.h
+++ b/engines/mm/mm1/maps/map40.h
@@ -79,7 +79,7 @@ private:
&Map40::special02
};
public:
- Map40() : Map(40, "rwl2", 0x702) {}
+ Map40() : Map(40, "rwl2", 0x702, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map41.h b/engines/mm/mm1/maps/map41.h
index 10011a9fe67..d4fdab9d3e3 100644
--- a/engines/mm/mm1/maps/map41.h
+++ b/engines/mm/mm1/maps/map41.h
@@ -84,7 +84,7 @@ private:
&Map41::special04
};
public:
- Map41() : Map(41, "enf1", 0xF04) {}
+ Map41() : Map(41, "enf1", 0xf04, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map42.h b/engines/mm/mm1/maps/map42.h
index 3f544cffe98..9dd61da4d1c 100644
--- a/engines/mm/mm1/maps/map42.h
+++ b/engines/mm/mm1/maps/map42.h
@@ -77,7 +77,7 @@ private:
&Map42::special04
};
public:
- Map42() : Map(42, "enf2", 0x704) {}
+ Map42() : Map(42, "enf2", 0x704, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map43.h b/engines/mm/mm1/maps/map43.h
index 7d361fc7d76..bb06b6b8d80 100644
--- a/engines/mm/mm1/maps/map43.h
+++ b/engines/mm/mm1/maps/map43.h
@@ -54,7 +54,7 @@ private:
&Map43::special08
};
public:
- Map43() : Map(43, "whitew", 0xA11) {}
+ Map43() : Map(43, "whitew", 0xa11, 1) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map44.h b/engines/mm/mm1/maps/map44.h
index 0afa92b4b16..6ea00fa9516 100644
--- a/engines/mm/mm1/maps/map44.h
+++ b/engines/mm/mm1/maps/map44.h
@@ -54,7 +54,7 @@ private:
&Map44::special07
};
public:
- Map44() : Map(44, "dragad", 0x107) {}
+ Map44() : Map(44, "dragad", 0x107, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map45.h b/engines/mm/mm1/maps/map45.h
index 85266c0a012..188b585c417 100644
--- a/engines/mm/mm1/maps/map45.h
+++ b/engines/mm/mm1/maps/map45.h
@@ -79,7 +79,7 @@ private:
&Map45::special21
};
public:
- Map45() : Map(45, "udrag1", 0xF05) {}
+ Map45() : Map(45, "udrag1", 0xf05, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map46.h b/engines/mm/mm1/maps/map46.h
index 66896ab4dea..e1ee8b47fbb 100644
--- a/engines/mm/mm1/maps/map46.h
+++ b/engines/mm/mm1/maps/map46.h
@@ -49,7 +49,7 @@ private:
&Map46::special06
};
public:
- Map46() : Map(46, "udrag2", 0xA00) {}
+ Map46() : Map(46, "udrag2", 0xa00, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map47.h b/engines/mm/mm1/maps/map47.h
index 9625ec3c884..15081d0c382 100644
--- a/engines/mm/mm1/maps/map47.h
+++ b/engines/mm/mm1/maps/map47.h
@@ -80,7 +80,7 @@ private:
&Map47::special23
};
public:
- Map47() : Map(47, "udrag3", 0x705) {}
+ Map47() : Map(47, "udrag3", 0x705, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map48.h b/engines/mm/mm1/maps/map48.h
index d51c3c7963f..c36a038bef6 100644
--- a/engines/mm/mm1/maps/map48.h
+++ b/engines/mm/mm1/maps/map48.h
@@ -31,7 +31,7 @@ namespace Maps {
class Map48 : public Map {
typedef void (Map48:: *SpecialFn)();
public:
- Map48() : Map(48, "demon", 0x412) {}
+ Map48() : Map(48, "demon", 0x412, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map49.h b/engines/mm/mm1/maps/map49.h
index 042f02ecd0c..5c9eeed46c2 100644
--- a/engines/mm/mm1/maps/map49.h
+++ b/engines/mm/mm1/maps/map49.h
@@ -72,7 +72,7 @@ private:
&Map49::special22
};
public:
- Map49() : Map(49, "alamar", 0xB07) {}
+ Map49() : Map(49, "alamar", 0xb07, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map50.h b/engines/mm/mm1/maps/map50.h
index 433a49fd7b8..38c98ca65fc 100644
--- a/engines/mm/mm1/maps/map50.h
+++ b/engines/mm/mm1/maps/map50.h
@@ -83,7 +83,7 @@ private:
&Map50::special23
};
public:
- Map50() : Map(50, "pp1", 0xF01) {}
+ Map50() : Map(50, "pp1", 0xf01, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map51.h b/engines/mm/mm1/maps/map51.h
index 262c7f4f952..337b308e81d 100644
--- a/engines/mm/mm1/maps/map51.h
+++ b/engines/mm/mm1/maps/map51.h
@@ -72,7 +72,7 @@ private:
&Map51::special19
};
public:
- Map51() : Map(51, "pp2", 0x701) {}
+ Map51() : Map(51, "pp2", 0x701, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map52.h b/engines/mm/mm1/maps/map52.h
index 9705f599cae..35210a2ea72 100644
--- a/engines/mm/mm1/maps/map52.h
+++ b/engines/mm/mm1/maps/map52.h
@@ -47,7 +47,7 @@ private:
&Map52::special06
};
public:
- Map52() : Map(52, "pp3", 0xE00) {}
+ Map52() : Map(52, "pp3", 0xe00, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map53.h b/engines/mm/mm1/maps/map53.h
index f0d7347c03a..0fa80022fdf 100644
--- a/engines/mm/mm1/maps/map53.h
+++ b/engines/mm/mm1/maps/map53.h
@@ -64,7 +64,7 @@ private:
&Map53::special14
};
public:
- Map53() : Map(53, "pp4", 0x201) {}
+ Map53() : Map(53, "pp4", 0x201, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map54.h b/engines/mm/mm1/maps/map54.h
index 039bcf44ed0..05a3195af80 100644
--- a/engines/mm/mm1/maps/map54.h
+++ b/engines/mm/mm1/maps/map54.h
@@ -52,7 +52,7 @@ private:
&Map54::special07
};
public:
- Map54() : Map(54, "astral", 0xB1A) {}
+ Map54() : Map(54, "astral", 0xb1a, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map_desert.h b/engines/mm/mm1/maps/map_desert.h
index 6e42ff4348d..650c818dbcf 100644
--- a/engines/mm/mm1/maps/map_desert.h
+++ b/engines/mm/mm1/maps/map_desert.h
@@ -52,8 +52,9 @@ public:
* Constructor
*/
MapDesert(uint index, const Common::String &name, uint16 id,
- byte &deadCount, RandomMode rndMode) :
- Map(index, name, id), _deadCount(deadCount), _randomMode(rndMode) {}
+ byte defaultSection, byte &deadCount, RandomMode rndMode) :
+ Map(index, name, id, defaultSection),
+ _deadCount(deadCount), _randomMode(rndMode) {}
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map_town.h b/engines/mm/mm1/maps/map_town.h
index 0f456f2a85a..8b0517fbbac 100644
--- a/engines/mm/mm1/maps/map_town.h
+++ b/engines/mm/mm1/maps/map_town.h
@@ -65,8 +65,9 @@ protected:
*/
void showSign(const Common::String &msg);
public:
- MapTown(uint index, const Common::String &name, uint16 id) :
- Map(index, name, id) {}
+ MapTown(uint index, const Common::String &name, uint16 id,
+ byte defaultSection) :
+ Map(index, name, id, defaultSection) {}
virtual ~MapTown() {}
};
Commit: 8296116d4d04126246599d9a9886d00717ea67b1
https://github.com/scummvm/scummvm/commit/8296116d4d04126246599d9a9886d00717ea67b1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:45+01:00
Commit Message:
MM: MM1: Support id/section pair for console map selection
Changed paths:
engines/mm/mm1/console.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 7700c200c6a..42cd2d33966 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -248,13 +248,20 @@ bool Console::cmdMapString(int argc, const char **argv) {
}
bool Console::cmdMap(int argc, const char **argv) {
- if (argc != 2 && argc != 4) {
- debugPrintf("map mapId [ xp, yp ]\n");
+ Maps::Maps &maps = g_globals->_maps;
+
+ if (argc < 2) {
+ debugPrintf("map <mapId section> | <mapNum [ xp, yp ]>\n");
return true;
- } else {
- Maps::Maps &maps = g_globals->_maps;
+
+ } else if (argc == 3) {
int mapId = strToInt(argv[1]);
- Maps::Map &map = *maps.getMap(mapId);
+ int section = strToInt(argv[2]);
+ maps.changeMap(mapId, section);
+
+ } else {
+ int mapNum = strToInt(argv[1]);
+ Maps::Map &map = *maps.getMap(mapNum);
int x = g_maps->_mapPos.x, y = g_maps->_mapPos.y;
if (argc == 4) {
@@ -265,9 +272,9 @@ bool Console::cmdMap(int argc, const char **argv) {
maps._mapPos.x = x;
maps._mapPos.y = y;
maps.changeMap(map.getId(), map.getDefaultSection());
-
- return false;
}
+
+ return false;
}
bool Console::cmdPos(int argc, const char **argv) {
Commit: eee2ce23cac4a3734ba932b4b177beadf198fac8
https://github.com/scummvm/scummvm/commit/eee2ce23cac4a3734ba932b4b177beadf198fac8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: More map fixes
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/locations.h
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map05.h
engines/mm/mm1/maps/map06.cpp
engines/mm/mm1/maps/map_town.cpp
engines/mm/mm1/views/maps/arrested.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 0de95f6e094..d6c5322f83a 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -933,6 +933,7 @@ maps:
stairs_up: "STAIRS GOING UP! TAKE THEM (Y/N)?"
stairs_down: "STAIRS GOING DOWN! TAKE THEM (Y/N)?"
wall_painted: "THE WALL IS PAINTED FROM CEILING TO\nFLOOR IN A BLACK AND WHITE CHECKERED\nPATTERN!"
+ tavern_inside: "STEP UP TO THE BAR (Y/N)?"
desert:
its_hot: "IT'S HOT... "
@@ -965,7 +966,6 @@ maps:
blacksmith_inside: "A MAN WEARING A LEATHER APRON SPEAKS:\n""DISTINGUISHED TRAVELERS, YOU''VE COME TOTHE RIGHT PLACE. CAN I HELP YOU (Y/N)?"""
inn_inside: "THE INNERKEEPER ASKS: ""WOULD YOU LIKE TO SIGN IN (Y/N)?"""
market_inside: "BEHIND THE COUNTER, AN OVERWEIGHT DWARF\nEXCLAIMS: ""YOU LOOK LIKE A HUNGRY BUNCH!\nWOULD YOU LIKE TO BUY SOME FOOD (Y/N)?"""
- tavern_inside: "STEP UP TO THE BAR (Y/N)?"
temple_inside: "SEVERAL ORANTELY ROBED CLERICS APPROACH\nTHE PARTY AND ASK, ""DO YOU SEEK OUR HELP (Y/N)?"""
training_inside: "BEFORE YOU ARE VARIOUS GROUPS ENGAGED INTRAINING EXERCISES. WORG,THE GUILDMASTERASKS, ""DO YOU REQUIRE TRAINING (Y/N)?"""
@@ -986,7 +986,6 @@ maps:
blacksmith_inside: """BUSILY FORGING A LONG SWORD,AN EXTREMELY\nBEAUTIFUL YOUNG GIRL SAYS WITH A\nSEDUCTIVE SMILE, ""CAN I HELP YOU (Y/N)?"""
inn_inside: "LARA, THE INKEEPERS VOLUPTUOUS\nDAUGHTER, ASKS IF YOU WILL BE SPENDING\nTHE NIGHT... SIGN IN (Y/N)?"
market_inside: "FROM BEHIND THE FRUIT STAND\nA SULTRY VOICE ASKS, ""SEE ANYTHING\nYOU LIKE (Y/N)?"""
- tavern_inside: "STEP UP TO THE BAR (Y/N)?"
temple_inside: "THE ONCE MAGNIFICENT TEMPLE SHOWS\nSIGNS OF NEGLECT AND DECAY. THE HIGH\nPRIESTESS ASKS,""NEED HELP (Y/N)?"""
training_inside: "A TALL, MUSCULAR FEMALE CLAD IN LEATHER\nARMOR APPROACHES ASKING, ""STRANGERS,\nARE YOU HERE FOR TRAINING (Y/N)?"""
@@ -1010,7 +1009,6 @@ maps:
blacksmith_inside: "A MAN ENCLOSED IN A STEEL CAGE SAYS,\n""CAN I HELP YOU FIND ANYTHING (Y/N)?"""
inn_inside: "STANDING BEHIND A LARGE DESK, A TALL\nBEARDED HALF-ORC GRUNTS, ""IF YOU DON'T\nSIGN IN, YOU CAN'T STAY! WELL (Y/N)?"""
market_inside: "A PUTRID SMELL PERVADES THE ROOM...\nLOOK FOR SOME FOOD (Y/N)?"
- tavern_inside: "STEP UP TO THE BAR (Y/N)?"
temple_inside: "AN ANCIENT LOOKING CLERIC STAGGERS UP TOTHE PARTY GASPING, ""I CAN HELP,\nREALLY I CAN!"" ACCEPT THE OFFER (Y/N)?"
training_inside: "SEVERAL ADVENTURERS ARMORED IN DRAGON\nSCALES, ADDRESS THE PARTY,\n""LOOKING FOR TRAINING (Y/N)?"""
@@ -1038,7 +1036,6 @@ maps:
blacksmith_inside: "A YOUNG GNOME MATERIALIZES, ASKING,\n""WOULD YOU BE WANTING MY SERVICES(Y/N)?"""
inn_inside: "AN EERIE SILENCE PERVADES THE DESERTED\nINN. SUDDENLY, A GHOSTLY APPARITION\nAPPEARS, ASKING, ""SIGN IN (Y/N)?"""
market_inside: "A FAINT OUTLINE OF A MAN APPEARS,\nSAYING, ""NEED SOME FEED (Y/N)?"""
- tavern_inside: "STEP UP TO THE BAR (Y/N)?'"
temple_inside: "BRIGHT LIGHTS SWIRL THROUGHOUT THE ROOM.A HORRIFYING VOICE SHRIEKS,\n""NEED HELP (Y/N)?"""
training_inside: "SEVERAL EMPTY SUITS OF ARMOR APPROACH\nASKING, ""NEED TRAINING (Y/N)?"""
@@ -1060,7 +1057,6 @@ maps:
blacksmith_inside: "A BOISTROUS HALF-ORC PROCLAIMS,\n""WE CARRY THE VERY LATEST,\nBROWSE (Y/N)?"""
inn_inside: "ADJUSTING HIS SPECTACLES, AN ELDERLY\nGNOME EYES THE PARTY AND ASKS,\n""SIGNING IN (Y/N)?"""
market_inside: "THE CHEF SAYS,""I ONLY SERVE THE BEST!\nHUNGRY (Y/N)?"""
- tavern_inside: "STEP UP TO THE BAR (Y/N)?"
training_inside: "THREE HUGE ARMOR CLAD KNIGHTS BARK IN\nUNISON, ""WANT A GOOD WORKOUT (Y/N)?"""
temple_inside: "SEVERAL FAT CLERICS WELCOME YOU.\nNEED HELP (Y/N)?"
@@ -1091,6 +1087,7 @@ maps:
button: "BUTTON ON THE WALL, PRESS IT (Y/N)?"
banner: "A BANNER READS:\nCORRIDOR OF ENDLESS ENCOUNTERS!"
wizard: "A CRAZED WIZARD EXCLAIMS,\n""ENCOUNTER THE 13, WIN THE PRIZE!"""
+ slide: "A SLIDE!"
map07:
do_not_disturb: "\n""DEMONS IN CONFERENCE, DO NOT DISTURB!"""
diff --git a/engines/mm/mm1/data/locations.h b/engines/mm/mm1/data/locations.h
index b00fc7f54e8..d41b880f311 100644
--- a/engines/mm/mm1/data/locations.h
+++ b/engines/mm/mm1/data/locations.h
@@ -70,7 +70,7 @@ struct BuyMiscData {
#define MAX_FOOD 40
struct MarketData {
- const byte FOOD_COST[4] = { 5, 10, 20, 200 };
+ const byte FOOD_COST[5] = { 5, 10, 20, 200, 50 };
};
struct TempleData {
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 74d2bb36319..5c03ae1ea9b 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -136,7 +136,7 @@ void Map02::special12() {
}
void Map02::special13() {
- send(SoundMessage(0, 1, STRING["maps.map01.zom0"]));
+ send(SoundMessage(0, 1, STRING["maps.map02.zom0"]));
}
void Map02::special14() {
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 071e9c5c6fa..60140464390 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -91,7 +91,6 @@ void Map03::special01() {
0, 1, STRING["maps.map03.telgoran2"],
[](const Common::KeyState &) {
InfoMessage info2(
- 0, 0, STRING["maps.map03.telgoran1"],
0, 1, STRING["maps.map03.telgoran3"],
[](const Common::KeyState &) {
g_events->close();
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index 13583c0a236..a2260a3ecf0 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -69,15 +69,13 @@ void Map04::special01() {
hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER1) != 0;
}
- bool hasScroll = false;
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- if (c.hasItem(VELLUM_SCROLL_ID)) {
- hasScroll = true;
- c._gold += 1500;
- break;
- }
- }
+ bool hasScroll = g_globals->_party.hasItem(VELLUM_SCROLL_ID);
+
+ auto callback = [](const Common::KeyState &) {
+ g_events->close();
+ g_maps->_mapPos.y = 6;
+ g_maps->_currentMap->updateGame();
+ };
if (hasCourier && hasScroll) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
@@ -90,13 +88,13 @@ void Map04::special01() {
send(InfoMessage(
0, 0, STRING["maps.map04.agar1"],
0, 1, STRING["maps.map04.agar2"],
- [](const Common::KeyState &) {
- }
+ callback
));
} else {
send(InfoMessage(
- 0, 0, STRING["maps.map03.telgoran1"],
- 0, 1, STRING["maps.map03.agar3"]
+ 0, 0, STRING["maps.map04.agar1"],
+ 0, 1, STRING["maps.map04.agar3"],
+ callback
));
}
}
@@ -122,6 +120,7 @@ void Map04::special04() {
));
} else {
// Sucks to be you
+ _data[MAP04_PASSAGE_OVERRIDE]++;
g_events->addView("Arrested");
}
}
@@ -139,10 +138,9 @@ void Map04::special07() {
}
void Map04::special08() {
- // Pick random run destination. This seems incredibly dangerous,
- // since couldn't it end up with the party in a wall?
g_maps->_mapPos.x = getRandomNumber(15);
g_maps->_mapPos.y = getRandomNumber(15);
+ redrawGame();
send(InfoMessage(0, 1, STRING["maps.poof"]));
}
@@ -150,19 +148,17 @@ void Map04::special08() {
void Map04::special09() {
visitedExit();
if (_data[MAP04_STAIRS_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
- if (_data[MAP04_STAIRS_OVERRIDE] < 255)
- _data[MAP04_STAIRS_OVERRIDE]++;
-
send(SoundMessage(
STRING["maps.stairs_down"],
[]() {
g_maps->_mapPos.x = 0;
g_maps->_mapPos.y = 7;
- g_maps->changeMap(0x202, 2);
+ g_maps->changeMap(0x202, 1);
}
));
} else {
// Sucks to be you
+ _data[MAP04_STAIRS_OVERRIDE]++;
g_events->addView("Arrested");
}
}
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 7a8fed5c4ca..8c6b8bc5117 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -93,7 +93,7 @@ void Map05::special05() {
}
void Map05::special06() {
- if (!hasScroll()) {
+ if (!g_globals->_party.hasItem(VELLUM_SCROLL_ID)) {
send(SoundMessage(
0, 1, STRING[!hasFlag() ? "maps.map05.man1" : "maps.map05.man2"],
[]() {
@@ -129,21 +129,21 @@ void Map05::special09() {
send(SoundMessage(
0, 1, STRING["maps.map05.arena_inside"],
[](const Common::KeyState &keyState) {
+ Map05 &map = *static_cast<Map05 *>(g_maps->_currentMap);
if (keyState.keycode == Common::KEYCODE_y) {
- (*g_maps->_currentMap)[MAP_47] = 2;
- (*g_maps->_currentMap)[MAP_33] = 6;
- (*g_maps->_currentMap)[MAP_MAX_MONSTERS] = 15;
+ g_events->close();
+ map[MAP_47] = 2;
+ map[MAP_33] = 6;
+ map[MAP_MAX_MONSTERS] = 15;
g_globals->_encounters._encounterType = Game::FORCE_SURPRISED;
g_globals->_encounters.execute();
} else if (keyState.keycode == Common::KEYCODE_n) {
- (*g_maps->_currentMap)[MAP_47] = 1;
- (*g_maps->_currentMap)[MAP_33] = 4;
- (*g_maps->_currentMap)[MAP_MAX_MONSTERS] = 10;
+ g_events->close();
+ map[MAP_47] = 1;
+ map[MAP_33] = 4;
+ map[MAP_MAX_MONSTERS] = 10;
g_globals->_treasure.clear();
-
- // TODO: Space key - is it used in-game?
- g_events->addKeypress(Common::KEYCODE_SPACE);
}
}
));
@@ -190,16 +190,6 @@ void Map05::showMessage(const Common::String &msg) {
));
}
-bool Map05::hasScroll() {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- const Character &c = g_globals->_party[i];
- if (c.hasItem(VELLUM_SCROLL_ID))
- return true;
- }
-
- return false;
-}
-
bool Map05::addScroll() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
diff --git a/engines/mm/mm1/maps/map05.h b/engines/mm/mm1/maps/map05.h
index 14c35516e84..95b0efdceb3 100644
--- a/engines/mm/mm1/maps/map05.h
+++ b/engines/mm/mm1/maps/map05.h
@@ -46,7 +46,6 @@ private:
void special14();
void encounter(int monsterId);
void showMessage(const Common::String &msg);
- static bool hasScroll();
static bool addScroll();
static bool hasFlag();
static void addFlag();
diff --git a/engines/mm/mm1/maps/map06.cpp b/engines/mm/mm1/maps/map06.cpp
index 9af6fab92c0..87a04e5a04c 100644
--- a/engines/mm/mm1/maps/map06.cpp
+++ b/engines/mm/mm1/maps/map06.cpp
@@ -114,6 +114,7 @@ void Map06::special01() {
void Map06::special02() {
if (_data[VAL1]) {
+ g_maps->_mapPos.x--;
slide();
} else {
checkPartyDead();
@@ -142,9 +143,6 @@ void Map06::special04() {
c._condition = UNCONSCIOUS;
}
}
- } else {
- // TODO: Space key - is it used in-game?
- g_events->addKeypress(Common::KEYCODE_SPACE);
}
}
@@ -152,7 +150,8 @@ void Map06::special06() {
send(SoundMessage(
STRING["maps.map06.button"],
[]() {
- byte &val1 = (*static_cast<Map06 *>(g_maps->_currentMap))[VAL1];
+ Map06 &map = *static_cast<Map06 *>(g_maps->_currentMap);
+ byte &val1 = map[VAL1];
val1 = val1 ? 0 : 1;
g_events->addKeypress(Common::KEYCODE_SPACE);
}
@@ -205,10 +204,15 @@ void Map06::special26() {
}
void Map06::slide() {
- send(SoundMessage(16, 1, STRING["maps.map06.slide"]));
_data[VAL2]++;
- updateGame();
+ SoundMessage msg(16, 1, STRING["maps.map06.slide"]);
+ msg._delaySeconds = 2;
+ msg._timeoutCallback = []() {
+ g_maps->_currentMap->updateGame();
+ };
+
+ send(msg);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
index 76771505638..4b49a87663e 100644
--- a/engines/mm/mm1/maps/map_town.cpp
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -66,7 +66,7 @@ void MapTown::tavern() {
visitedBusiness();
send(SoundMessage(
- STRING[Common::String::format("maps.map%.2u.tavern_inside", _mapIndex)],
+ STRING[Common::String::format("maps.tavern_inside", _mapIndex)],
[]() {
g_events->addView("Tavern");
}
diff --git a/engines/mm/mm1/views/maps/arrested.cpp b/engines/mm/mm1/views/maps/arrested.cpp
index 3844e9ee4d1..9f4da497a55 100644
--- a/engines/mm/mm1/views/maps/arrested.cpp
+++ b/engines/mm/mm1/views/maps/arrested.cpp
@@ -45,6 +45,9 @@ void Arrested::draw() {
}
bool Arrested::msgKeypress(const KeypressMessage &msg) {
+ if (endDelay())
+ return true;
+
switch (msg.keycode) {
case Common::KEYCODE_a:
attack();
@@ -114,7 +117,7 @@ void Arrested::surrender(int numYears) {
clearSurface();
Sound::sound(SOUND_2);
writeString(0, 1, STRING["maps.map04.sentence"]);
- writeNumber('0' + numYears);
+ writeNumber(numYears);
(*g_maps->_currentMap)[MAP04_TREASURE_STOLEN] = 0;
delaySeconds(3);
Commit: 3321c4397b7f7a4a1a57725d798145677e1d304e
https://github.com/scummvm/scummvm/commit/3321c4397b7f7a4a1a57725d798145677e1d304e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: Do case insensitive answer comparisons
Changed paths:
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map32.cpp
engines/mm/mm1/views/maps/access_code.cpp
engines/mm/mm1/views/maps/chess.cpp
engines/mm/mm1/views/maps/ice_princess.cpp
engines/mm/mm1/views/maps/orango.cpp
engines/mm/mm1/views/maps/ruby.cpp
engines/mm/mm1/views/maps/trivia.cpp
engines/mm/mm1/views/maps/volcano_god.cpp
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index ff263e2144a..569ead969dd 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -71,7 +71,7 @@ void Map08::special01() {
send(SoundMessage(
STRING["maps.stairs_up"],
[]() {
- g_maps->_mapPos = Common::Point(0, 14);
+ g_maps->_mapPos = Common::Point(14, 1);
g_maps->changeMap(0xa00, 2);
}
));
diff --git a/engines/mm/mm1/maps/map32.cpp b/engines/mm/mm1/maps/map32.cpp
index db5ab4aec07..138f5079906 100644
--- a/engines/mm/mm1/maps/map32.cpp
+++ b/engines/mm/mm1/maps/map32.cpp
@@ -129,9 +129,9 @@ void Map32::special05() {
}
void Map32::passwordEntered(const Common::String &password) {
- if ((_data[PASSWORD_INDEX] & 0x80) || password !=
- STRING[Common::String::format("maps.map32.passwords.%d",
- _data[PASSWORD_INDEX])]) {
+ if ((_data[PASSWORD_INDEX] & 0x80) ||
+ !password.equalsIgnoreCase(STRING[Common::String::format("maps.map32.passwords.%d",
+ _data[PASSWORD_INDEX])])) {
g_maps->_mapPos.x--;
updateGame();
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
index 1ecf8795250..bd80a815957 100644
--- a/engines/mm/mm1/views/maps/access_code.cpp
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -54,7 +54,7 @@ void AccessCode::answerEntered() {
for (int i = 0; i < 10 && map[ANSWER_OFFSET + i]; ++i)
properCode += map[ANSWER_OFFSET + i] + 0x1f;
- if (_answer == properCode)
+ if (_answer.equalsIgnoreCase(properCode))
correctCode();
else
incorrectCode();
diff --git a/engines/mm/mm1/views/maps/chess.cpp b/engines/mm/mm1/views/maps/chess.cpp
index 0db7db6960f..d65482e1d52 100644
--- a/engines/mm/mm1/views/maps/chess.cpp
+++ b/engines/mm/mm1/views/maps/chess.cpp
@@ -54,7 +54,7 @@ void Chess::answerEntered() {
for (int i = 0; i < 22; ++i)
properAnswer += map[ANSWER_OFFSET + i] + 48;
- if (_answer == properAnswer) {
+ if (_answer.equalsIgnoreCase(properAnswer)) {
InfoMessage msg(
16, 2, STRING["maps.map19.correct"],
[]() {
diff --git a/engines/mm/mm1/views/maps/ice_princess.cpp b/engines/mm/mm1/views/maps/ice_princess.cpp
index 23730770f89..ebe41fc7345 100644
--- a/engines/mm/mm1/views/maps/ice_princess.cpp
+++ b/engines/mm/mm1/views/maps/ice_princess.cpp
@@ -52,7 +52,7 @@ void IcePrincess::answerEntered() {
for (int i = 0; i < 4; ++i)
properAnswer += (map[ANSWER_OFFSET + i] & 0x7f) + 64;
- if (_answer == properAnswer) {
+ if (_answer.equalsIgnoreCase(properAnswer)) {
InfoMessage msg(
16, 2, STRING["maps.map19.correct"],
[]() {
diff --git a/engines/mm/mm1/views/maps/orango.cpp b/engines/mm/mm1/views/maps/orango.cpp
index a8243849b57..1d5c4852a90 100644
--- a/engines/mm/mm1/views/maps/orango.cpp
+++ b/engines/mm/mm1/views/maps/orango.cpp
@@ -50,7 +50,7 @@ void Orango::answerEntered() {
for (int i = 0; i < 15 && map[ANSWER_OFFSET + i]; ++i)
properAnswer += (map[ANSWER_OFFSET + i] & 0x7f) + 29;
- if (_answer == properAnswer) {
+ if (_answer.equalsIgnoreCase(properAnswer)) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
c._flags[13] |= CHARFLAG13_ALAMAR;
diff --git a/engines/mm/mm1/views/maps/ruby.cpp b/engines/mm/mm1/views/maps/ruby.cpp
index 23af5b1b094..ef4eca42061 100644
--- a/engines/mm/mm1/views/maps/ruby.cpp
+++ b/engines/mm/mm1/views/maps/ruby.cpp
@@ -48,7 +48,7 @@ void Ruby::answerEntered() {
for (int i = 0; i < 12 && map[ANSWER_OFFSET + i]; ++i)
properAnswer += map[ANSWER_OFFSET + i] - 64;
- if (_answer == properAnswer) {
+ if (_answer.equalsIgnoreCase(properAnswer)) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
g_globals->_party[i]._flags[5] |= CHARFLAG5_20;
}
diff --git a/engines/mm/mm1/views/maps/trivia.cpp b/engines/mm/mm1/views/maps/trivia.cpp
index ea590afe979..57d15010d49 100644
--- a/engines/mm/mm1/views/maps/trivia.cpp
+++ b/engines/mm/mm1/views/maps/trivia.cpp
@@ -53,7 +53,7 @@ void Trivia::draw() {
}
void Trivia::answerEntered() {
- if (_answer == _correctAnswer) {
+ if (_answer.equalsIgnoreCase(_correctAnswer)) {
send(InfoMessage(STRING["maps.map21.correct"]));
g_globals->_party[0]._gems += 50;
Sound::sound(SOUND_3);
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
index ddef9fe964d..ba5ad970161 100644
--- a/engines/mm/mm1/views/maps/volcano_god.cpp
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -105,7 +105,7 @@ void VolcanoGod::answerEntered() {
for (int i = 0; i < 8 && map[ANSWER_OFFSET + i]; ++i)
properAnswer += map[ANSWER_OFFSET + i] + 30;
- if (_answer == properAnswer) {
+ if (_answer.equalsIgnoreCase(properAnswer)) {
(*g_maps->_currentMap)[VAL1]++;
g_events->addAction(KEYBIND_SEARCH);
} else {
Commit: 97db5ed0dd58621afec7b889f286d0298abeb206
https://github.com/scummvm/scummvm/commit/97db5ed0dd58621afec7b889f286d0298abeb206
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: Map 8 fixes
Changed paths:
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map08.h
engines/mm/mm1/views/maps/access_code.cpp
engines/mm/mm1/views/maps/access_code.h
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 569ead969dd..63b3c9e21a6 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -29,7 +29,13 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 163
+#define MAX_CODE_LENGTH 10
+#define ANSWER_OFFSET 147
+#define CODE_ENTERED 163
+#define CODE_FAILURES 408
+
+static const byte OFFSETS1[8] = { 146, 98, 150, 102, 153, 105, 157, 109 };
+static const byte OFFSETS2[8] = { 130, 82, 134, 86, 137, 89, 141, 93 };
void Map08::special() {
// Scan for special actions on the map cell
@@ -78,7 +84,7 @@ void Map08::special01() {
}
void Map08::special02() {
- if (_data[VAL1]) {
+ if (_data[CODE_ENTERED]) {
g_events->addView("AccessCode");
} else {
checkPartyDead();
@@ -96,7 +102,7 @@ void Map08::special05() {
}
void Map08::special06() {
- if (_data[VAL1]) {
+ if (_data[CODE_ENTERED]) {
reduceHP();
send(InfoMessage(18, 2, STRING["maps.map08.zap"]));
@@ -107,7 +113,7 @@ void Map08::special06() {
}
void Map08::special08() {
- if (_data[VAL1]) {
+ if (_data[CODE_ENTERED]) {
send(InfoMessage(0, 1, STRING["maps.map08.dancing_lights"]));
Sound::sound(SOUND_3);
} else {
@@ -129,6 +135,64 @@ void Map08::addTreasure() {
g_events->addAction(KEYBIND_SEARCH);
}
+void Map08::codeEntered(const Common::String &code) {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ Common::String properCode;
+ for (int i = 0; i < 10 && map[ANSWER_OFFSET + i]; ++i)
+ properCode += map[ANSWER_OFFSET + i] + 0x1f;
+
+ if (code.equalsIgnoreCase(properCode))
+ correctCode();
+ else
+ incorrectCode();
+}
+
+void Map08::correctCode() {
+ _data[CODE_ENTERED] = 0;
+
+ for (int i = 0; i < 8; ++i)
+ _states[OFFSETS1[i]] ^= 4;
+ for (int i = 0; i < 8; ++i)
+ _states[OFFSETS2[i]] ^= 0x40;
+ _states[119] ^= 0x10;
+ _states[120] ^= 1;
+
+ send(SoundMessage(STRING["maps.map08.good_code"]));
+}
+
+void Map08::incorrectCode() {
+ SoundMessage msg(
+ STRING["maps.map08.bad_code"],
+ []() {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
+ map[CODE_FAILURES]++;
+
+ if (map[CODE_FAILURES] != 2 && map[CODE_FAILURES] < 20) {
+ g_maps->_mapPos.y--;
+ map.updateGame();
+ return;
+ } else if (map[CODE_FAILURES] != 2) {
+ map[MM1::Maps::MAP_31] = 10;
+ }
+
+ InfoMessage msg2(
+ 0, 1, STRING["maps.map08.bad_code"],
+ 17, 2, STRING["maps.map08.alarm"],
+ []() {
+ g_globals->_encounters.execute();
+ }
+ );
+ msg2._delaySeconds = 2;
+
+ g_events->send(msg2);
+ Sound::sound(SOUND_3);
+ }
+ );
+
+ msg._delaySeconds = 2;
+ send(msg);
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map08.h b/engines/mm/mm1/maps/map08.h
index d91b350026d..319ea433050 100644
--- a/engines/mm/mm1/maps/map08.h
+++ b/engines/mm/mm1/maps/map08.h
@@ -67,6 +67,17 @@ private:
&Map08::special20,
&Map08::special20
};
+
+ /**
+ * Correct code entered
+ */
+ void correctCode();
+
+ /**
+ * Incorrect code entered
+ */
+ void incorrectCode();
+
public:
Map08() : Map(8, "cave4", 0x202, 1) {}
@@ -74,6 +85,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Access code entered
+ */
+ void codeEntered(const Common::String &code);
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/access_code.cpp b/engines/mm/mm1/views/maps/access_code.cpp
index bd80a815957..2ef8252441d 100644
--- a/engines/mm/mm1/views/maps/access_code.cpp
+++ b/engines/mm/mm1/views/maps/access_code.cpp
@@ -29,14 +29,6 @@ namespace MM1 {
namespace Views {
namespace Maps {
-#define MAX_CODE_LENGTH 10
-#define ANSWER_OFFSET 147
-#define VAL1 163
-#define VAL2 408
-
-static const byte OFFSETS1[8] = { 146, 98, 150, 102, 153, 105, 157, 109 };
-static const byte OFFSETS2[8] = { 130, 82, 134, 86, 137, 89, 141, 93 };
-
AccessCode::AccessCode() :
AnswerEntry("AccessCode", Common::Point(16, 3), 8) {
_bounds = getLineBounds(20, 24);
@@ -49,49 +41,8 @@ void AccessCode::draw() {
}
void AccessCode::answerEntered() {
- MM1::Maps::Map &map = *g_maps->_currentMap;
- Common::String properCode;
- for (int i = 0; i < 10 && map[ANSWER_OFFSET + i]; ++i)
- properCode += map[ANSWER_OFFSET + i] + 0x1f;
-
- if (_answer.equalsIgnoreCase(properCode))
- correctCode();
- else
- incorrectCode();
-}
-
-void AccessCode::correctCode() {
- MM1::Maps::Map &map = *g_maps->_currentMap;
- Sound::sound(SOUND_2);
- clearSurface();
- writeString(0, 1, STRING["maps.map08.good_code"]);
-
- map[VAL1] = 0;
- for (int i = 0; i < 8; ++i)
- map._states[OFFSETS1[i]] ^= 4;
- for (int i = 0; i < 8; ++i)
- map._states[OFFSETS2[i]] ^= 0x40;
- map._states[119] ^= 0x10;
- map._states[120] ^= 1;
-}
-
-void AccessCode::incorrectCode() {
- MM1::Maps::Map &map = *g_maps->_currentMap;
- Sound::sound(SOUND_2);
- clearSurface();
- writeString(0, 1, STRING["maps.map08.bad_code"]);
-
- if (map[VAL2] != 2 && map[VAL2] < 20) {
- g_maps->_mapPos.y--;
- g_events->send("Game", GameMessage("UPDATE"));
- return;
- } else if (map[VAL2] != 2) {
- map[MM1::Maps::MAP_31] = 10;
- }
-
- writeString(17, 2, STRING["maps.map08.alarm"]);
- Sound::sound(SOUND_3);
- delaySeconds(2);
+ MM1::Maps::Map08 &map = *static_cast<MM1::Maps::Map08 *>(g_maps->_currentMap);
+ map.codeEntered(_answer);
}
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/access_code.h b/engines/mm/mm1/views/maps/access_code.h
index f9c9804a08d..9f5f780dfe0 100644
--- a/engines/mm/mm1/views/maps/access_code.h
+++ b/engines/mm/mm1/views/maps/access_code.h
@@ -30,17 +30,6 @@ namespace Views {
namespace Maps {
class AccessCode : public AnswerEntry {
-private:
- /**
- * Correct code entered
- */
- void correctCode();
-
- /**
- * Incorrect code entered
- */
- void incorrectCode();
-
protected:
/**
* Called when the code has been entered
Commit: 1c31a18d2ed9625496556057e358f4fe142d371b
https://github.com/scummvm/scummvm/commit/1c31a18d2ed9625496556057e358f4fe142d371b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: More map fixes
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/items.h
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map09.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map11.h
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/views/maps/volcano_god.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index d6c5322f83a..6ffcaf1b00c 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1121,6 +1121,7 @@ maps:
shrine1: "THE SHRINE OF OKZAR, PRAY (Y/N)?"
shrine2: "YOUR LEADER IS OF CLEAR MIND."
shrine3: "YOUR LEADER IS INCONSISTENT. BEGONE!"
+ speed: "THE FLAME OF AGILITY GRANTS THOSE WHO\nARE WORTHY +4 SPEED!"
stalactites: "STALACTITES SHOWER THE PARTY!"
map10:
@@ -1148,6 +1149,7 @@ maps:
ladder: "A LADDER GOING UP, TAKE IT (Y/N)?"
map12:
+ ladder_up: "LADDER UP, CLIMB (Y/N)?"
polyhedron1: "ATOP A CRYSTAL PYRAMID SPINS A GLOWING\nPOLYHEDRON. STOP IT ON SIDE (1-9)?"
polyhedron2: "THE POLYHEDRON IS SET ON %c\nSPIN IT (Y/N)?"
polyhedron3: "A GLOWING POLYHEDRON IS SET ON SIDE %c%c"
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index b3aeb0c67e9..6e15ef0b622 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -45,6 +45,7 @@ enum ItemId {
DIAMOND_KEY_ID = 240,
CACTUS_NECTAR_ID = 241,
MAP_OF_DESERT_ID = 242,
+ LASER_BLASTER_ID = 243,
DRAGONS_TOOTH_ID = 244,
WYVERN_EYE_ID = 245,
MEDUSA_HEAD_ID = 246,
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 63b3c9e21a6..5e4d3593c2e 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -31,7 +31,7 @@ namespace Maps {
#define MAX_CODE_LENGTH 10
#define ANSWER_OFFSET 147
-#define CODE_ENTERED 163
+#define CODE_ARMED 163
#define CODE_FAILURES 408
static const byte OFFSETS1[8] = { 146, 98, 150, 102, 153, 105, 157, 109 };
@@ -84,7 +84,7 @@ void Map08::special01() {
}
void Map08::special02() {
- if (_data[CODE_ENTERED]) {
+ if (_data[CODE_ARMED]) {
g_events->addView("AccessCode");
} else {
checkPartyDead();
@@ -102,7 +102,7 @@ void Map08::special05() {
}
void Map08::special06() {
- if (_data[CODE_ENTERED]) {
+ if (_data[CODE_ARMED]) {
reduceHP();
send(InfoMessage(18, 2, STRING["maps.map08.zap"]));
@@ -113,7 +113,7 @@ void Map08::special06() {
}
void Map08::special08() {
- if (_data[CODE_ENTERED]) {
+ if (_data[CODE_ARMED]) {
send(InfoMessage(0, 1, STRING["maps.map08.dancing_lights"]));
Sound::sound(SOUND_3);
} else {
@@ -148,7 +148,7 @@ void Map08::codeEntered(const Common::String &code) {
}
void Map08::correctCode() {
- _data[CODE_ENTERED] = 0;
+ _data[CODE_ARMED] = 0;
for (int i = 0; i < 8; ++i)
_states[OFFSETS1[i]] ^= 4;
diff --git a/engines/mm/mm1/maps/map09.cpp b/engines/mm/mm1/maps/map09.cpp
index 1153bc1008c..8ef4ff300c7 100644
--- a/engines/mm/mm1/maps/map09.cpp
+++ b/engines/mm/mm1/maps/map09.cpp
@@ -99,7 +99,7 @@ void Map09::special06() {
}
}
- g_events->send(SoundMessage(0, 1, STRING["maps.map07.accuracy"]));
+ g_events->send(SoundMessage(0, 1, STRING["maps.map09.accuracy"]));
}
void Map09::special07() {
@@ -111,7 +111,7 @@ void Map09::special07() {
}
}
- g_events->send(SoundMessage(0, 1, STRING["maps.map07.speed"]));
+ g_events->send(SoundMessage(0, 1, STRING["maps.map09.speed"]));
}
void Map09::special08() {
@@ -120,32 +120,41 @@ void Map09::special08() {
c._flags[5] |= CHARFLAG5_8;
}
- const Character &leader = g_globals->_party[0];
-
- if (leader._alignment == leader._alignmentInitial) {
- send(SoundMessage(
- 0, 1, STRING["maps.map09.shrine1"],
- 0, 2, STRING["maps.map09.shrine2"]
- ));
-
- g_globals->_treasure._items[2] = getRandomNumber(26) + 120;
- g_globals->_treasure.setGold(120);
- g_events->addAction(KEYBIND_SEARCH);
-
- } else {
- send(SoundMessage(
- 0, 1, STRING["maps.map09.shrine1"],
- 0, 2, STRING["maps.map09.shrine3"]
- ));
+ send(SoundMessage(
+ 0, 1, STRING["maps.map09.shrine1"],
+ []() {
+ const Character &leader = g_globals->_party[0];
+
+ if (leader._alignment == leader._alignmentInitial) {
+ SoundMessage msg(
+ STRING["maps.map09.shrine2"],
+ []() {
+ g_globals->_treasure._items[2] = getRandomNumber(26) + 120;
+ g_globals->_treasure.setGold(120);
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ );
+ msg._delaySeconds = 2;
+ g_events->send(msg);
- // TODO: Check this is right. Original set y twice
- g_maps->_mapPos = Common::Point(5, 13);
- g_maps->changeMap(0x201, 3);
- }
+ } else {
+ SoundMessage msg(
+ STRING["maps.map09.shrine3"],
+ []() {
+ // TODO: Check this is right. Original set y twice
+ g_maps->_mapPos = Common::Point(5, 13);
+ g_maps->changeMap(0x201, 3);
+ }
+ );
+ msg._delaySeconds = 2;
+ g_events->send(msg);
+ }
+ }
+ ));
}
void Map09::special09() {
- send(SoundMessage(0, 1, STRING["maps.map09.stalactities"]));
+ send(SoundMessage(0, 1, STRING["maps.map09.stalactites"]));
reduceHP();
}
@@ -154,7 +163,7 @@ void Map09::special14() {
if (g_globals->_activeSpells._s.levitate) {
send(SoundMessage(
- 0, 1, STRING["maps.map09.map"],
+ 0, 1, STRING["maps.map09.pit"],
0, 2, STRING["maps.map09.levitation"]
));
} else {
@@ -166,9 +175,14 @@ void Map09::special14() {
c._hpBase /= 2;
}
- send(SoundMessage(
- 0, 1, STRING["maps.map09.map"]
- ));
+ SoundMessage msg(
+ STRING["maps.map09.pit"],
+ []() {
+ g_globals->_encounters.execute();
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
}
}
@@ -183,7 +197,6 @@ void Map09::special18() {
getRandomNumber(g_globals->_party.size()) - 1
];
-
if (!(g_globals->_currCharacter->_condition & BAD_CONDITION)) {
// Chosen character is okay, so blast them
g_globals->_currCharacter->_condition = BAD_CONDITION | DEAD;
@@ -191,8 +204,7 @@ void Map09::special18() {
// Chosen character is disabled, so instead
// remove the SP from all members of the party
for (uint i = 0; i < g_globals->_party.size(); ++i) {
- g_globals->_currCharacter = &g_globals->_party[i];
- g_globals->_currCharacter->_sp._current = 0;
+ g_globals->_party[i]._sp._current = 0;
}
}
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index ab82fd0d4ac..a652f150f64 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -141,9 +141,7 @@ void Map10::special23() {
reduceHP();
if (getRandomNumber(4) == 4) {
- Sound::sound(SOUND_2);
- Sound::sound(SOUND_3);
- InfoMessage msg(
+ SoundMessage msg(
0, 1, STRING["maps.map10.pit"],
[]() {
g_globals->_encounters.execute();
@@ -151,9 +149,10 @@ void Map10::special23() {
);
msg._delaySeconds = 2;
send(msg);
+ Sound::sound(SOUND_3);
} else {
- send(SoundMessage(0, 1, STRING["maps.map10.pit"]));
+ send(SoundMessage(STRING["maps.map10.pit"]));
Sound::sound(SOUND_3);
}
}
@@ -166,7 +165,7 @@ void Map10::special29() {
void Map10::special30() {
Game::Encounter &enc = g_globals->_encounters;
int monsterCount = getRandomNumber(4) + 3;
- g_globals->_treasure._items[2] = 252;
+ g_globals->_treasure._items[2] = THUNDRANIUM_ID;
enc.clearMonsters();
for (int i = 0; i < monsterCount; ++i)
@@ -184,7 +183,7 @@ void Map10::special31() {
void Map10::special32() {
Game::Encounter &enc = g_globals->_encounters;
int monsterCount = getRandomNumber(4) + 3;
- g_globals->_treasure._items[2] = 243;
+ g_globals->_treasure._items[2] = LASER_BLASTER_ID;
enc.clearMonsters();
for (int i = 0; i < monsterCount; ++i)
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 059ced16619..1300c3b4e5a 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -29,6 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define MAX_ANSWER_LENGTH 8
+#define ANSWER_OFFSET 636
#define VAL1 641
#define VAL2 642
#define VAL3 643
@@ -79,6 +81,7 @@ void Map11::special00() {
void Map11::special01() {
if (_data[VAL1]) {
+ // Teleport to outside the Inn of Sorpigal
g_maps->_mapPos = Common::Point(8, 5);
g_maps->changeMap(0x604, 1);
} else {
@@ -96,6 +99,8 @@ void Map11::special03() {
}
void Map11::special04() {
+ g_maps->clearSpecial();
+
send(SoundMessage(STRING["maps.map11.virgin"],
[](const Common::KeyState &ks) {
switch (ks.keycode) {
@@ -185,6 +190,26 @@ void Map11::setDialChar(char c) {
_data[VAL2 + _dialIndex] = c;
}
+void Map11::clue() {
+ g_maps->_mapPos = Common::Point(0, 5);
+ updateGame();
+}
+
+void Map11::riddleAnswer(const Common::String &answer) {
+ Common::String properAnswer;
+ for (int i = 0; i < 8 && _data[ANSWER_OFFSET + i]; ++i)
+ properAnswer += _data[ANSWER_OFFSET + i] + 30;
+
+ if (answer.equalsIgnoreCase(properAnswer)) {
+ _data[VAL1]++;
+ g_globals->_treasure._items[2] = KEY_CARD_ID;
+ g_events->addAction(KEYBIND_SEARCH);
+ } else {
+ g_maps->_mapPos = Common::Point(7, 2);
+ g_maps->changeMap(0xf04, 2);
+ }
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map11.h b/engines/mm/mm1/maps/map11.h
index 189f44ee753..ad3b95af7f8 100644
--- a/engines/mm/mm1/maps/map11.h
+++ b/engines/mm/mm1/maps/map11.h
@@ -78,6 +78,16 @@ public:
* Set the alphabetic character for the current dial
*/
void setDialChar(char c);
+
+ /**
+ * Volcano god's clue
+ */
+ void clue();
+
+ /**
+ * Volcano god's riddle answer
+ */
+ void riddleAnswer(const Common::String &answer);
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index 18d26a707f8..1af1afe7829 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -56,10 +56,10 @@ void Map12::special() {
void Map12::special00() {
visitedExit();
send(SoundMessage(
- STRING["maps.ladder_up"],
+ STRING["maps.map12.ladder_up"],
[]() {
g_maps->_mapPos = Common::Point(7, 13);
- g_maps->changeMap(0x105, 2);
+ g_maps->changeMap(0x106, 2);
}
));
}
@@ -115,15 +115,15 @@ void Map12::special01() {
}
void Map12::special02() {
- polyhedron('1', (unsigned char)182);
+ polyhedron('1', 0x80 + '6');
}
void Map12::special03() {
- polyhedron('1', (unsigned char)179);
+ polyhedron('1', 0x80 + '3');
}
void Map12::special04() {
- polyhedron('1', (unsigned char)176);
+ polyhedron('1', 0x80 + '0');
}
void Map12::special05() {
@@ -131,15 +131,15 @@ void Map12::special05() {
}
void Map12::special06() {
- polyhedron('1', (unsigned char)178);
+ polyhedron('1', 0x80 + '2');
}
void Map12::special07() {
- polyhedron('1', (unsigned char)181);
+ polyhedron('1', 0x80 + '5');
}
void Map12::special08() {
- polyhedron('1', (unsigned char)180);
+ polyhedron('1', 0x80 + '4');
}
void Map12::special09() {
diff --git a/engines/mm/mm1/views/maps/volcano_god.cpp b/engines/mm/mm1/views/maps/volcano_god.cpp
index ba5ad970161..a2b2f537e18 100644
--- a/engines/mm/mm1/views/maps/volcano_god.cpp
+++ b/engines/mm/mm1/views/maps/volcano_god.cpp
@@ -29,10 +29,6 @@ namespace MM1 {
namespace Views {
namespace Maps {
-#define MAX_ANSWER_LENGTH 8
-#define ANSWER_OFFSET 636
-#define VAL1 641
-
VolcanoGod::VolcanoGod() :
AnswerEntry("VolcanoGod", Common::Point(9, 3), 8) {
}
@@ -84,7 +80,8 @@ bool VolcanoGod::msgKeypress(const KeypressMessage &msg) {
}
void VolcanoGod::challenge() {
- static_cast<MM1::Maps::Map11 *>(g_maps->_currentMap)->challenge();
+ MM1::Maps::Map11 &map = *static_cast<MM1::Maps::Map11 *>(g_maps->_currentMap);
+ map.challenge();
}
void VolcanoGod::riddle() {
@@ -94,24 +91,15 @@ void VolcanoGod::riddle() {
}
void VolcanoGod::clue() {
+ MM1::Maps::Map11 &map = *static_cast<MM1::Maps::Map11 *>(g_maps->_currentMap);
close();
- g_maps->_mapPos = Common::Point(0, 5);
- g_events->send("Game", GameMessage("UPDATE"));
+ map.clue();
}
void VolcanoGod::answerEntered() {
- MM1::Maps::Map &map = *g_maps->_currentMap;
- Common::String properAnswer;
- for (int i = 0; i < 8 && map[ANSWER_OFFSET + i]; ++i)
- properAnswer += map[ANSWER_OFFSET + i] + 30;
-
- if (_answer.equalsIgnoreCase(properAnswer)) {
- (*g_maps->_currentMap)[VAL1]++;
- g_events->addAction(KEYBIND_SEARCH);
- } else {
- g_maps->_mapPos = Common::Point(7, 2);
- g_maps->changeMap(0xf04, 2);
- }
+ MM1::Maps::Map11 &map = *static_cast<MM1::Maps::Map11 *>(g_maps->_currentMap);
+ close();
+ map.riddleAnswer(_answer);
}
} // namespace Maps
Commit: 6a40d6762a28ef6db7a0853bb7b432a0060ca236
https://github.com/scummvm/scummvm/commit/6a40d6762a28ef6db7a0853bb7b432a0060ca236
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: Extra quit checks for main event loop
Changed paths:
engines/mm/mm1/events.cpp
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 16f865c0a03..f3eea9fea0d 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -56,13 +56,16 @@ void Events::runGame() {
}
Common::Event e;
- for (;;) {
+ bool quitFlag = false;
+ while (!quitFlag) {
while (g_system->getEventManager()->pollEvent(e)) {
if (e.type == Common::EVENT_QUIT ||
- e.type == Common::EVENT_RETURN_TO_LAUNCHER)
- return;
- else
+ e.type == Common::EVENT_RETURN_TO_LAUNCHER) {
+ quitFlag = true;
+ break;
+ } else {
processEvent(e);
+ }
}
g_system->delayMillis(10);
Commit: d9011fd241e44fcb09fc6c973d1c7ad34635add0
https://github.com/scummvm/scummvm/commit/d9011fd241e44fcb09fc6c973d1c7ad34635add0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: Allow timed game messages to close due to keypress
Changed paths:
engines/mm/mm1/views/game_messages.cpp
diff --git a/engines/mm/mm1/views/game_messages.cpp b/engines/mm/mm1/views/game_messages.cpp
index d1ea2612937..ea04d51cff2 100644
--- a/engines/mm/mm1/views/game_messages.cpp
+++ b/engines/mm/mm1/views/game_messages.cpp
@@ -89,7 +89,10 @@ bool GameMessages::msgKeypress(const KeypressMessage &msg) {
g_events->clearViews();
addView("Dead");
- } else if (g_events->focusedView() == this && !isDelayActive()) {
+ } else if (g_events->focusedView()) {
+ if (endDelay())
+ return true;
+
if (_keyCallback) {
_keyCallback(msg);
} else if (msg.keycode == Common::KEYCODE_n) {
Commit: ffd370d4cffd68bbfce0de8466eb84fd697f2395
https://github.com/scummvm/scummvm/commit/ffd370d4cffd68bbfce0de8466eb84fd697f2395
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: More map fixes
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map14.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map16.cpp
engines/mm/mm1/maps/map17.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 6ffcaf1b00c..60ce2fd8288 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1193,7 +1193,7 @@ maps:
map17:
options: "1) RED THORAC 2) BLUE OGRAM\n3) GREEN BAGAR 4) YELLOW LIMRA\n5) PURPLE SAGRAN 6) ORANGE OOLAK\n7) BLACK DRESIDION 8) WHITE DILITHIUM"
bridge: "A WOODEN BRIDGE EXTENDES ACROSS THE\nOCEAN INTO THE MIST. A HOODED FIGURE\nMATERIALIZES, ""TO CROSS YOU MUST EACH\nANSWER A QUESTION, ACCEPT (Y/N)?"""
- color: "WHAT IS YOUR COLOR(1-8)?"
+ color: "WHAT IS YOUR COLOR (1-8)?"
wrong: "WRONG!"
correct: "CORRECT!"
islands: "ATOP THIS PEAK 5 ISLANDS CAN BE SEEN\nTO THE SOUTHEAST"
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
index 26ba95c944d..20da662eb56 100644
--- a/engines/mm/mm1/maps/map14.cpp
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -88,7 +88,7 @@ void Map14::special00() {
ks.keycode == Common::KEYCODE_n) {
g_events->close();
- // TODO: The original seems to be backwards
+ // Note: The original seems to be backwards
if (ks.keycode == Common::KEYCODE_n &&
getRandomNumber(3) == 3) {
g_maps->_mapPos = Common::Point(15, 10);
@@ -122,7 +122,7 @@ void Map14::special02() {
} else if (_data[VAL3]) {
_data[VAL3] = 0;
} else {
- g_events->findView("View")->redraw();
+ send("View", DrawGraphicMessage(65 + 6));
send(SoundMessage(
STRING["maps.map14.castle"],
@@ -130,10 +130,12 @@ void Map14::special02() {
Map14 &map = *static_cast<Map14 *>(g_maps->_currentMap);
if (ks.keycode == Common::KEYCODE_y) {
g_events->close();
- map[VAL3]++;
+ map[VAL3] = 0xff;
+ map.updateGame();
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->close();
- map[VAL3] = 0xff;
+ map[VAL3]++;
+ map.updateGame();
}
}
));
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index 8decba12a8c..6b9fe759305 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -31,7 +31,7 @@ namespace Maps {
#define VAL1 350
#define VAL2 118
-#define VAL3 361
+#define ITEM_ID 361
#define GEMS 362
void Map15::special() {
@@ -104,9 +104,15 @@ void Map15::special01() {
Game::Encounter &enc = g_globals->_encounters;
if (_data[VAL2]) {
- send(SoundMessage(STRING["maps.map15.dragon"]));
- g_globals->_treasure._items[2] = 244;
- g_events->addAction(KEYBIND_SEARCH);
+ SoundMessage msg(
+ STRING["maps.map15.body"],
+ []() {
+ g_globals->_treasure._items[2] = DRAGONS_TOOTH_ID;
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ );
+ msg._delaySeconds = 5;
+ send(msg);
} else {
_data[VAL2]++;
@@ -148,13 +154,13 @@ void Map15::special03() {
}
void Map15::special04() {
- _data[VAL3] = 250;
+ _data[ITEM_ID] = PIRATES_MAP_A_ID;
_data[GEMS] = 100;
cove();
}
void Map15::special05() {
- _data[VAL3] = 251;
+ _data[ITEM_ID] = PIRATES_MAP_B_ID;
_data[GEMS] = 200;
cove();
}
@@ -165,12 +171,21 @@ void Map15::special06() {
[](const Common::KeyState &ks) {
if (ks.keycode == Common::KEYCODE_y) {
g_events->close();
- g_globals->_treasure._items[2] = 233;
+ g_globals->_treasure._items[2] = KINGS_PASS_ID;
g_events->addAction(KEYBIND_SEARCH);
+
} else if (ks.keycode == Common::KEYCODE_n) {
- g_events->send(SoundMessage(STRING["maps.map15.percella1"]));
- g_maps->_mapPos = Common::Point(14, 2);
- updateGame();
+ g_events->close();
+
+ SoundMessage msg(
+ STRING["maps.map15.percella2"],
+ []() {
+ g_maps->_mapPos = Common::Point(14, 2);
+ updateGame();
+ }
+ );
+ msg._delaySeconds = 5;
+ g_events->send(msg);
}
}
));
@@ -189,7 +204,7 @@ void Map15::cove() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- int idx = c._backpack.indexOf(map[VAL3]);
+ int idx = c._backpack.indexOf(map[ITEM_ID]);
if (idx != -1) {
c._backpack.removeAt(idx);
g_globals->_treasure.setGold(2000);
diff --git a/engines/mm/mm1/maps/map16.cpp b/engines/mm/mm1/maps/map16.cpp
index 4affe5f80f5..46278d0c4c0 100644
--- a/engines/mm/mm1/maps/map16.cpp
+++ b/engines/mm/mm1/maps/map16.cpp
@@ -94,8 +94,8 @@ void Map16::special00() {
}
_data[VAL1]++;
- send(SoundMessage(STRING["maps.map16.water"],
- [](const Common::KeyState &ks) {
+ SoundMessage msg(STRING["maps.map16.water"],
+ []() {
Game::Encounter &enc = g_globals->_encounters;
enc.clearMonsters();
@@ -107,15 +107,17 @@ void Map16::special00() {
enc._flag = true;
enc.execute();
}
- ));
+ );
+ msg._delaySeconds = 5;
+ send(msg);
}
}
void Map16::special01() {
send(SoundMessage(STRING["maps.map16.wheel"],
[]() {
- // Original called sound 1 20 times. This seems excessive
- Sound::sound(SOUND_1);
+ for (int i = 0; i < 20; ++i)
+ Sound::sound(SOUND_1);
static_cast<Map16 *>(g_maps->_currentMap)->wheelSpin();
}
@@ -124,7 +126,7 @@ void Map16::special01() {
void Map16::special02() {
_data[VAL1] = 0;
- g_events->addAction(KEYBIND_SEARCH);
+ none160();
}
void Map16::special03() {
@@ -191,7 +193,7 @@ void Map16::wheelSpin() {
}
}
- msg._lines.push_back(Line(0, i, line));
+ msg._lines.push_back(Line(0, 1 + i, line));
}
// Display the results
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 1b698d9a0ba..8901c565836 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -30,8 +30,8 @@ namespace MM1 {
namespace Maps {
#define VAL1 509
-#define VAL2 510
-#define VAL3 511
+#define COLOR 510
+#define CORRECT_ANSWERS 511
void Map17::special() {
Game::Encounter &enc = g_globals->_encounters;
@@ -70,28 +70,31 @@ void Map17::special() {
updateGame();
} else {
- g_events->addAction(KEYBIND_SEARCH);
+ none160();
}
}
void Map17::special00() {
- send(SoundMessage("maps.map17.islands"));
+ send(SoundMessage(STRING["maps.map17.islands"]));
}
void Map17::special01() {
- send(SoundMessage(STRING["maps.map17.bridge"],
+ SoundMessage msg(STRING["maps.map17.bridge"],
[]() {
static_cast<Map17 *>(g_maps->_currentMap)->askQuestion();
}
- ));
+ );
+
+ msg._largeMessage = true;
+ send(msg);
}
void Map17::special02() {
- if (_data[VAL3]) {
- g_globals->_treasure._items[2] = 236;
+ if (_data[CORRECT_ANSWERS]) {
+ g_globals->_treasure._items[2] = CORAL_KEY_ID;
g_events->addAction(KEYBIND_SEARCH);
} else {
- g_events->addKeypress((Common::KeyCode)211);
+ none160();
}
}
@@ -102,7 +105,8 @@ void Map17::special03() {
void Map17::askQuestion(uint partyIndex) {
if (partyIndex >= g_globals->_party.size()) {
- if (_data[VAL3]) {
+ // Entire party has answered the question
+ if (_data[CORRECT_ANSWERS]) {
g_maps->_mapPos.y = 2;
updateGame();
} else {
@@ -122,16 +126,19 @@ void Map17::askQuestion(uint partyIndex) {
Map17 &map = *static_cast<Map17 *>(g_maps->_currentMap);
if (ks.keycode >= Common::KEYCODE_1 &&
ks.keycode <= Common::KEYCODE_9) {
- map[VAL2] = ks.ascii - '1';
+ map[COLOR] = ks.ascii - '1';
Common::String line;
Character &c = *g_globals->_currCharacter;
- int val = c._flags[2] & 0xf;
- if (!val || (val & 7) != map[VAL2]) {
+ int color = c._flags[2] & 0xf;
+
+ // If a color hasn't been designated yet from talking to Gypsy,
+ // or it has but the wrong color is selected, eradicate them
+ if (!color || (color & 7) != map[COLOR]) {
c._condition = ERADICATED;
line = STRING["maps.map17.wrong"];
} else {
- map[VAL3]++;
+ map[CORRECT_ANSWERS]++;
c._flags[4] |= CHARFLAG4_80;
line = STRING["maps.map17.correct"];
}
@@ -142,7 +149,7 @@ void Map17::askQuestion(uint partyIndex) {
msg2._delaySeconds = 1;
msg2._lines.push_back(Line(0, 0, STRING["maps.map17.color"]));
msg2._lines.push_back(Line(0, 2, STRING["maps.map17.options"]));
- msg2._lines.push_back(Line(16, 5, line));
+ msg2._lines.push_back(Line(16, 6, line));
msg2._timeoutCallback = []() {
Map17 &map17 = *static_cast<Map17 *>(g_maps->_currentMap);
map17.askQuestion(map17[VAL1] + 1);
Commit: f65b2eade156602188d783bb083831b455939605
https://github.com/scummvm/scummvm/commit/f65b2eade156602188d783bb083831b455939605
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:46+01:00
Commit Message:
MM: MM1: Further map fixes
Changed paths:
engines/mm/mm1/maps/map21.cpp
engines/mm/mm1/maps/map21.h
engines/mm/mm1/maps/map22.cpp
engines/mm/mm1/views/maps/trivia.cpp
diff --git a/engines/mm/mm1/maps/map21.cpp b/engines/mm/mm1/maps/map21.cpp
index 2948b0d59b8..48efa5983ba 100644
--- a/engines/mm/mm1/maps/map21.cpp
+++ b/engines/mm/mm1/maps/map21.cpp
@@ -29,8 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 159
-#define VAL2 160
+#define QUESTION_NUM 159
+#define TRIVIA_ENABLED 160
#define TRIVIA_COST 500
void Map21::special() {
@@ -77,8 +77,8 @@ void Map21::special00() {
g_maps->clearSpecial();
for (uint i = 0; i < g_globals->_party.size(); ++i) {
- g_globals->_currCharacter = &g_globals->_party[i];
- g_globals->_currCharacter->_flags[7] |= CHARFLAG7_20;
+ Character &c = g_globals->_party[i];
+ c._flags[7] |= CHARFLAG7_20;
}
SoundMessage msg(
@@ -107,16 +107,20 @@ void Map21::special01() {
STRING["maps.map21.free_trivia"],
[]() {
Map21 &map = *static_cast<Map21 *>(g_maps->_currentMap);
- map[VAL2]++;
+ map[TRIVIA_ENABLED]++;
}
));
}
void Map21::special02() {
+ if (_data[TRIVIA_ENABLED])
+ return;
+
send(SoundMessage(
STRING["maps.map21.trivia_island"],
[](const Common::KeyState &ks) {
if (ks.keycode == Common::KEYCODE_y) {
+ MM1::Maps::Map &map = *g_maps->_currentMap;
g_events->close();
for (uint i = 0; i < g_globals->_party.size(); ++i) {
@@ -125,6 +129,7 @@ void Map21::special02() {
if (g_globals->_currCharacter->_gold >= TRIVIA_COST) {
c._gold -= 500;
g_maps->clearSpecial();
+ map[TRIVIA_ENABLED]++;
return;
}
}
@@ -143,11 +148,20 @@ void Map21::special02() {
}
void Map21::special03() {
- send("Trivia", 0);
+ askTrivia(0);
}
void Map21::special04() {
- send("Trivia", 0);
+ askTrivia(g_maps->_mapPos.x - 5);
+}
+
+void Map21::askTrivia(int questionNum) {
+ _data[QUESTION_NUM] = questionNum;
+
+ if (_data[TRIVIA_ENABLED]) {
+ g_maps->clearSpecial();
+ send("Trivia", questionNum);
+ }
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map21.h b/engines/mm/mm1/maps/map21.h
index 29fb21f4dfc..54a3ad84a7c 100644
--- a/engines/mm/mm1/maps/map21.h
+++ b/engines/mm/mm1/maps/map21.h
@@ -47,6 +47,8 @@ private:
&Map21::special04,
&Map21::special04
};
+
+ void askTrivia(int questionNum);
public:
Map21() : Map(21, "areab4", 0xd03, 1) {}
diff --git a/engines/mm/mm1/maps/map22.cpp b/engines/mm/mm1/maps/map22.cpp
index 319b3030848..3d9e13f51a9 100644
--- a/engines/mm/mm1/maps/map22.cpp
+++ b/engines/mm/mm1/maps/map22.cpp
@@ -29,7 +29,7 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define WHISTLE_COUNT 107
+#define WHISTLE_GIVEN 107
static const byte MONSTER_ID1[5] = { 13, 12, 13, 12, 11 };
static const byte MONSTER_ID2[5] = { 6, 6, 5, 5, 4 };
@@ -69,7 +69,9 @@ void Map22::special00() {
}
Sound::sound(SOUND_3);
- send(InfoMessage(STRING["maps.map22.chest"]));
+ InfoMessage msg(STRING["maps.map22.chest"]);
+ msg._largeMessage = true;
+ send(msg);
for (uint i = 0; i < g_globals->_party.size() && !hasFlags; ++i) {
Character &c = g_globals->_party[i];
@@ -81,12 +83,13 @@ void Map22::special00() {
// Add amulet to player
if (!c._backpack.full()) {
- _data[WHISTLE_COUNT]++;
+ _data[WHISTLE_GIVEN]++;
c._backpack.add(RUBY_WHISTLE_ID, 200);
+ break;
}
}
- if (!_data[WHISTLE_COUNT]) {
+ if (!_data[WHISTLE_GIVEN]) {
// Entire party's inventory full. So screw it, replace
// the last item in the last character's backpack
g_globals->_currCharacter->_backpack.removeAt(INVENTORY_COUNT - 1);
@@ -106,7 +109,7 @@ void Map22::special02() {
[]() {
g_maps->clearSpecial();
if (g_maps->_mapPos.x == 5) {
- g_globals->_treasure._items[2] = 234;
+ g_globals->_treasure._items[2] = MERCHANTS_PASS_ID;
g_events->addAction(KEYBIND_SEARCH);
} else {
diff --git a/engines/mm/mm1/views/maps/trivia.cpp b/engines/mm/mm1/views/maps/trivia.cpp
index 57d15010d49..b212fdf9c91 100644
--- a/engines/mm/mm1/views/maps/trivia.cpp
+++ b/engines/mm/mm1/views/maps/trivia.cpp
@@ -29,18 +29,16 @@ namespace MM1 {
namespace Views {
namespace Maps {
-#define VAL1 159
-#define VAL2 160
-
Trivia::Trivia() :
- AnswerEntry("Trivia", Common::Point(9, 5), 14) {
+ AnswerEntry("Trivia", Common::Point(9, 7), 14) {
+ _bounds = getLineBounds(17, 24);
}
bool Trivia::msgValue(const ValueMessage &msg) {
_question = STRING[Common::String::format(
"maps.map21.questions.%d", msg._value)];
_correctAnswer = STRING[Common::String::format(
- "maps.map21.questions.%d", msg._value)];
+ "maps.map21.answers.%d", msg._value)];
open();
return true;
@@ -48,11 +46,14 @@ bool Trivia::msgValue(const ValueMessage &msg) {
void Trivia::draw() {
clearSurface();
- writeString(0, 1, STRING["maps.map19.ice_princess"]);
+ writeString(0, 1, _question);
+ writeString(0, 7, STRING["maps.map21.answer"]);
AnswerEntry::draw();
}
void Trivia::answerEntered() {
+ close();
+
if (_answer.equalsIgnoreCase(_correctAnswer)) {
send(InfoMessage(STRING["maps.map21.correct"]));
g_globals->_party[0]._gems += 50;
@@ -61,7 +62,7 @@ void Trivia::answerEntered() {
} else {
g_maps->_mapPos.x = 15;
g_events->send("Game", GameMessage("UPDATE"));
- send(InfoMessage(STRING["maps.map19.incorrect"]));
+ send(InfoMessage(STRING["maps.map21.incorrect"]));
}
}
Commit: 75e5d978c71a3473888c35d8fb0fe143872d4096
https://github.com/scummvm/scummvm/commit/75e5d978c71a3473888c35d8fb0fe143872d4096
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: Fix desert map base class crash
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map26.h
engines/mm/mm1/maps/map27.h
engines/mm/mm1/maps/map30.h
engines/mm/mm1/maps/map31.h
engines/mm/mm1/maps/map_desert.cpp
engines/mm/mm1/maps/map_desert.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 60ce2fd8288..adf68535fe4 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -940,6 +940,7 @@ maps:
youre_lost: "YOU'RE LOST!!!"
whirlwind: "A WHIRLWIND SWOOPS THE PARTY AWAY!"
sandstorm: "A VIOLENT SANDSTORM BLASTS THE PARTY!"
+ lost: "YOU'RE LOST!!!"
prisoners:
child: "A SMALL CHILD SHIVERS FEARFULLY AS YOU\nAPPROACH.\n\n"
@@ -1299,7 +1300,7 @@ maps:
map25:
slab: "A LARGE SLAB OF CORAL BLOCKS A PASSAGE!\n"
key: "YOUR CORAL KEY FITS PERFECTLY\nIN THE LOCK, ENTER (Y/N)?"
- ship: "AT THE WATERS EDGE ARE THE DECAYING\nREMAINS OF A LARGE SHIP. SEARCH(Y/N)?"
+ ship: "AT THE WATERS EDGE ARE THE DECAYING\nREMAINS OF A LARGE SHIP. SEARCH (Y/N)?"
natives: "CRAZED NATIVES ATTACK!"
volcano: "THE VOLCANO ERUPTS!"
pirates: "PIRATES ATTACK!"
diff --git a/engines/mm/mm1/maps/map26.h b/engines/mm/mm1/maps/map26.h
index acf26dee6c6..e206dee45a5 100644
--- a/engines/mm/mm1/maps/map26.h
+++ b/engines/mm/mm1/maps/map26.h
@@ -44,8 +44,7 @@ private:
&Map26::special03
};
public:
- Map26() : MapDesert(26, "aread1", 0x505, 2,
- _data[247], MapDesert::RND_FULL) {}
+ Map26() : MapDesert(26, "aread1", 0x505, 2, 247, MapDesert::RND_FULL) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map27.h b/engines/mm/mm1/maps/map27.h
index 700e4d3064c..c008bdac4bf 100644
--- a/engines/mm/mm1/maps/map27.h
+++ b/engines/mm/mm1/maps/map27.h
@@ -48,8 +48,7 @@ private:
&Map27::special05
};
public:
- Map27() : MapDesert(27, "aread2", 0xb05, 2,
- _data[66], MapDesert::RND_BASIC) {}
+ Map27() : MapDesert(27, "aread2", 0xb05, 2, 66, MapDesert::RND_BASIC) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map30.h b/engines/mm/mm1/maps/map30.h
index 1b3d2b5f625..57c4b75f4e8 100644
--- a/engines/mm/mm1/maps/map30.h
+++ b/engines/mm/mm1/maps/map30.h
@@ -43,8 +43,7 @@ private:
&Map30::special03
};
public:
- Map30() : MapDesert(30, "areae1", 0x112, 2,
- _data[137], MapDesert::RND_FULL) {}
+ Map30() : MapDesert(30, "areae1", 0x112, 2, 137, MapDesert::RND_FULL) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map31.h b/engines/mm/mm1/maps/map31.h
index 29ec133ce2a..e8a499c4160 100644
--- a/engines/mm/mm1/maps/map31.h
+++ b/engines/mm/mm1/maps/map31.h
@@ -46,8 +46,7 @@ private:
&Map31::special06
};
public:
- Map31() : MapDesert(31, "areae2", 0x706, 3, _data[80],
- MapDesert::RND_BASIC) {}
+ Map31() : MapDesert(31, "areae2", 0x706, 3, 80, MapDesert::RND_BASIC) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map_desert.cpp b/engines/mm/mm1/maps/map_desert.cpp
index a67c393de69..96f6131a163 100644
--- a/engines/mm/mm1/maps/map_desert.cpp
+++ b/engines/mm/mm1/maps/map_desert.cpp
@@ -39,7 +39,8 @@ void MapDesert::desert() {
lost();
}
- _deadCount = 0;
+ byte &deadCount = _data[_deadCountOffset];
+ deadCount = 0;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
@@ -55,12 +56,12 @@ void MapDesert::desert() {
} else {
// When endurance reaches, character becomes living impaired
c._condition = DEAD | BAD_CONDITION;
- _deadCount++;
+ deadCount++;
}
}
}
- if (_deadCount)
+ if (deadCount)
g_events->findView("GameParty")->redraw();
switch (_randomMode) {
diff --git a/engines/mm/mm1/maps/map_desert.h b/engines/mm/mm1/maps/map_desert.h
index 650c818dbcf..e157c05fcdf 100644
--- a/engines/mm/mm1/maps/map_desert.h
+++ b/engines/mm/mm1/maps/map_desert.h
@@ -32,7 +32,7 @@ class MapDesert : public Map {
protected:
enum RandomMode { RND_BASIC, RND_FULL };
private:
- byte &_deadCount;
+ int _deadCountOffset;
RandomMode _randomMode;
/**
@@ -52,9 +52,9 @@ public:
* Constructor
*/
MapDesert(uint index, const Common::String &name, uint16 id,
- byte defaultSection, byte &deadCount, RandomMode rndMode) :
+ byte defaultSection, int deadCountOffset, RandomMode rndMode) :
Map(index, name, id, defaultSection),
- _deadCount(deadCount), _randomMode(rndMode) {}
+ _deadCountOffset(deadCountOffset), _randomMode(rndMode) {}
};
} // namespace Maps
Commit: 391f7ab4f8700ef1ada663ef7b9448477090810b
https://github.com/scummvm/scummvm/commit/391f7ab4f8700ef1ada663ef7b9448477090810b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: More map fixes
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map27.cpp
engines/mm/mm1/maps/map29.cpp
engines/mm/mm1/maps/map29.h
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/views/maps/chess.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index adf68535fe4..beefdc164b1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1311,13 +1311,13 @@ maps:
map26:
scorpion: "SUDDENLY, A GARGANTUAN SCORPION ATTACKS!"
trading_post: "A SMALL TRIBE OF DESERT NOMADS HAVE\nESTABLISHED A TRADING POST HERE.\nTRADE ITEM (Y/N)?"
- leader_nothing: "YOUR LEADER HAS NOTHING TO TRADE!"
+ nothing_to_trade: "YOUR LEADER HAS NOTHING TO TRADE!"
kilburn: "KILBURN, C-3 6-14"
map27:
pool: "THE POOL OF WISDOM GRANTS THOSE WHO ARE\nWORTHY +4 PERSONALITY."
retreat: "CLERICAL RETREAT"
- clerics: "WE ARE THE CLERICS OF THE "
+ clerics: "WE ARE THE CLERICS OF THE"
cured: "YOUR PARTY IS CURED!"
alignment: "YOUR ALIGNMENT IS RESTORED!"
curses: "ALL CURSES ARE REMOVED!"
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 60140464390..38a5a9eb651 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -38,8 +38,7 @@ void Map03::special() {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
-
+ if (g_maps->_forwardMask & _data[80 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map27.cpp b/engines/mm/mm1/maps/map27.cpp
index 06db321b65f..c174e335698 100644
--- a/engines/mm/mm1/maps/map27.cpp
+++ b/engines/mm/mm1/maps/map27.cpp
@@ -121,7 +121,6 @@ void Map27::special04() {
}
g_globals->_activeSpells._s.cursed = 0;
-
}
void Map27::special05() {
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
index a45b3e56ef3..d3826b6829a 100644
--- a/engines/mm/mm1/maps/map29.cpp
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -29,7 +29,8 @@ namespace MM {
namespace MM1 {
namespace Maps {
-#define VAL1 110
+#define ANSWER_OFFSET 67
+#define BEAST_FLAG 110
void Map29::special() {
Game::Encounter &enc = g_globals->_encounters;
@@ -95,7 +96,7 @@ void Map29::special00() {
}
void Map29::special01() {
- if (_data[VAL1]) {
+ if (_data[BEAST_FLAG]) {
g_maps->clearSpecial();
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
@@ -119,7 +120,7 @@ void Map29::special01() {
Game::Encounter &enc = g_globals->_encounters;
Map29 &map = *static_cast<Map29 *>(g_maps->_currentMap);
g_events->close();
- map[VAL1]++;
+ map[BEAST_FLAG]++;
enc.clearMonsters();
enc.addMonster(3, 12);
@@ -139,7 +140,7 @@ void Map29::special01() {
void Map29::special02() {
if (!g_globals->_party.hasItem(B_QUEEN_IDOL_ID) ||
!g_globals->_party.hasItem(W_QUEEN_IDOL_ID)) {
- send(SoundMessage(STRING["maps.map29.begone"]));
+ begone();
} else {
g_events->addView("Chess");
}
@@ -168,10 +169,50 @@ void Map29::special03() {
send(msg);
}
+void Map29::chessAnswer(const Common::String &answer) {
+ Common::String properAnswer;
+
+ for (int i = 0; i < 22; ++i)
+ properAnswer += _data[ANSWER_OFFSET + i] - 48;
+
+ if (answer.equalsIgnoreCase(properAnswer)) {
+ redrawGame();
+
+ InfoMessage msg(
+ 16, 2, STRING["maps.map19.correct"],
+ []() {
+ MM1::Maps::Map29 &map29 = *static_cast<MM1::Maps::Map29 *>(g_maps->_currentMap);
+
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._exp += 25000;
+ }
+
+ g_maps->_mapPos.y = 7;
+ map29.updateGame();
+ }
+ );
+
+ msg._delaySeconds = 2;
+ send(msg);
+ Sound::sound(SOUND_3);
+ Sound::sound(SOUND_3);
+
+ } else {
+ begone();
+ }
+
+}
+
void Map29::begone() {
- send(SoundMessage(STRING["maps.map29.begone"]));
g_maps->_mapPos.y = 7;
- updateGame();
+ SoundMessage msg(STRING["maps.map29.begone"],
+ []() {
+ updateGame();
+ }
+ );
+ msg._delaySeconds = 2;
+ send(msg);
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map29.h b/engines/mm/mm1/maps/map29.h
index 1d1273d9e9a..d2f91194f1e 100644
--- a/engines/mm/mm1/maps/map29.h
+++ b/engines/mm/mm1/maps/map29.h
@@ -42,6 +42,9 @@ private:
&Map29::special02,
&Map29::special03
};
+
+ void begone();
+
public:
Map29() : Map(29, "aread4", 0x801, 2) {}
@@ -50,7 +53,10 @@ public:
*/
void special() override;
- void begone();
+ /**
+ * Chess answer handler
+ */
+ void chessAnswer(const Common::String &answer);
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index ee97a1c8caa..0774147ec27 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -40,7 +40,7 @@ void Map30::special() {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[65 + i]) {
+ if (g_maps->_forwardMask & _data[55 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index d78c6642b67..04be2549e78 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -215,16 +215,11 @@ void Maps::synchronizeCurrent(Common::Serializer &s) {
s.syncAsByte(_mapPos.x);
s.syncAsByte(_mapPos.y);
s.syncAsByte(_forwardMask);
- s.syncAsByte(_backwardsMask);
- s.syncAsByte(_leftMask);
- s.syncAsByte(_rightMask);
- s.syncAsSByte(_forwardOffset);
- s.syncAsSByte(_backwardsOffset);
- s.syncAsSByte(_leftOffset);
- s.syncAsSByte(_rightOffset);
-
- if (s.isLoading())
+
+ if (s.isLoading()) {
+ updateMasksOffsets();
changeMap(_id, _section);
+ }
}
void Maps::select(uint16 id, byte section) {
@@ -284,38 +279,17 @@ void Maps::loadTown(TownId townId) {
void Maps::town15setup() {
_forwardMask = DIRMASK_N;
- _leftMask = DIRMASK_W;
- _rightMask = DIRMASK_E;
- _backwardsMask = DIRMASK_S;
-
- _forwardOffset = MAP_W;
- _leftOffset = -1;
- _rightOffset = 1;
- _backwardsOffset = -MAP_W;
+ updateMasksOffsets();
}
void Maps::town23setup() {
_forwardMask = DIRMASK_W;
- _leftMask = DIRMASK_S;
- _rightMask = DIRMASK_N;
- _backwardsMask = DIRMASK_E;
-
- _forwardOffset = -1;
- _leftOffset = -MAP_W;
- _rightOffset = MAP_W;
- _backwardsOffset = 1;
+ updateMasksOffsets();
}
void Maps::town4setup() {
_forwardMask = DIRMASK_E;
- _leftMask = DIRMASK_N;
- _rightMask = DIRMASK_S;
- _backwardsMask = DIRMASK_W;
-
- _forwardOffset = 1;
- _leftOffset = MAP_W;
- _rightOffset = -MAP_W;
- _backwardsOffset = -1;
+ updateMasksOffsets();
}
uint Maps::getIndex(uint16 id, byte section) {
@@ -392,38 +366,18 @@ void Maps::loadTile() {
}
void Maps::turnLeft() {
- DirMask tempMask = _rightMask;
- _rightMask = _forwardMask;
_forwardMask = _leftMask;
- _leftMask = _backwardsMask;
- _backwardsMask = tempMask;
-
- int8 tempOffset = _rightOffset;
- _rightOffset = _forwardOffset;
- _forwardOffset = _leftOffset;
- _leftOffset = _backwardsOffset;
- _backwardsOffset = tempOffset;
+ updateMasksOffsets();
}
void Maps::turnRight() {
- DirMask tempMask = _leftMask;
- _leftMask = _forwardMask;
_forwardMask = _rightMask;
- _rightMask = _backwardsMask;
- _backwardsMask = tempMask;
-
- int8 tempOffset = _leftOffset;
- _leftOffset = _forwardOffset;
- _forwardOffset = _rightOffset;
- _rightOffset = _backwardsOffset;
- _backwardsOffset = tempOffset;
+ updateMasksOffsets();
}
void Maps::turnAround() {
- SWAP(g_maps->_forwardMask, g_maps->_backwardsMask);
- SWAP(g_maps->_leftMask, g_maps->_rightMask);
- SWAP(g_maps->_forwardOffset, g_maps->_backwardsOffset);
- SWAP(g_maps->_leftOffset, g_maps->_rightOffset);
+ _forwardMask = _backwardsMask;
+ updateMasksOffsets();
}
void Maps::step(const Common::Point &delta) {
@@ -483,6 +437,57 @@ Common::Point Maps::getMoveDelta(byte mask) {
}
}
+void Maps::updateMasksOffsets() {
+ switch (_forwardMask) {
+ case DIRMASK_N:
+ _leftMask = DIRMASK_W;
+ _rightMask = DIRMASK_E;
+ _backwardsMask = DIRMASK_S;
+
+ _forwardOffset = MAP_W;
+ _leftOffset = -1;
+ _rightOffset = 1;
+ _backwardsOffset = -MAP_W;
+ break;
+
+ case DIRMASK_E:
+ _leftMask = DIRMASK_N;
+ _rightMask = DIRMASK_S;
+ _backwardsMask = DIRMASK_W;
+
+ _forwardOffset = 1;
+ _leftOffset = MAP_W;
+ _rightOffset = -MAP_W;
+ _backwardsOffset = -1;
+ break;
+
+ case DIRMASK_S:
+ _leftMask = DIRMASK_E;
+ _rightMask = DIRMASK_W;
+ _backwardsMask = DIRMASK_N;
+
+ _forwardOffset = -MAP_W;
+ _leftOffset = 1;
+ _rightOffset = -1;
+ _backwardsOffset = MAP_W;
+ break;
+
+ case DIRMASK_W:
+ _leftMask = DIRMASK_S;
+ _rightMask = DIRMASK_N;
+ _backwardsMask = DIRMASK_E;
+
+ _forwardOffset = -1;
+ _leftOffset = -MAP_W;
+ _rightOffset = MAP_W;
+ _backwardsOffset = 1;
+ break;
+
+ default:
+ break;
+ }
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 24666340b0f..00e90e8b50a 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -91,6 +91,11 @@ private:
*/
void town4setup();
+ /**
+ * Updates masks/offsets based on _forwardMask
+ */
+ void updateMasksOffsets();
+
public:
Common::Array<Graphics::ManagedSurface> _tiles[3];
uint _mapId = (uint)-1;
diff --git a/engines/mm/mm1/views/maps/chess.cpp b/engines/mm/mm1/views/maps/chess.cpp
index d65482e1d52..1adb3ff5299 100644
--- a/engines/mm/mm1/views/maps/chess.cpp
+++ b/engines/mm/mm1/views/maps/chess.cpp
@@ -29,10 +29,8 @@ namespace MM1 {
namespace Views {
namespace Maps {
-#define ANSWER_OFFSET 67
-
Chess::Chess() :
- AnswerEntry("Chess", Common::Point(10, 7), 23) {
+ AnswerEntry("Chess", Common::Point(10, 6), 23) {
_bounds = getLineBounds(17, 24);
}
@@ -49,35 +47,9 @@ void Chess::draw() {
void Chess::answerEntered() {
MM1::Maps::Map29 &map = *static_cast<MM1::Maps::Map29 *>(g_maps->_currentMap);
- Common::String properAnswer;
-
- for (int i = 0; i < 22; ++i)
- properAnswer += map[ANSWER_OFFSET + i] + 48;
-
- if (_answer.equalsIgnoreCase(properAnswer)) {
- InfoMessage msg(
- 16, 2, STRING["maps.map19.correct"],
- []() {
- MM1::Maps::Map29 &map29 = *static_cast<MM1::Maps::Map29 *>(g_maps->_currentMap);
-
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- c._exp += 25000;
- }
-
- g_maps->_mapPos.y = 7;
- map29.updateGame();
- }
- );
-
- msg._delaySeconds = 2;
- send(msg);
- Sound::sound(SOUND_3);
- Sound::sound(SOUND_3);
-
- } else {
- map.begone();
- }
+ clearSurface();
+ close();
+ map.chessAnswer(_answer);
}
} // namespace Maps
Commit: 8455b0189183c3de18f37d07bba9c8c044979f1f
https://github.com/scummvm/scummvm/commit/8455b0189183c3de18f37d07bba9c8c044979f1f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: Fixed showing gems in search results
Changed paths:
engines/mm/mm1/views/search.cpp
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index e93c781234a..d0b3f45a29e 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -321,7 +321,7 @@ void Search::getTreasure() {
int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 3 : 1;
send("View", DrawGraphicMessage(gfxNum + 65));
- draw();
+ redraw();
}
void Search::drawTreasure() {
Commit: 01870da12b10e61cd4f1bffe98d5b3fbfaae4932
https://github.com/scummvm/scummvm/commit/01870da12b10e61cd4f1bffe98d5b3fbfaae4932
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: Further map fixes
Changed paths:
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/map30.h
engines/mm/mm1/maps/map31.cpp
engines/mm/mm1/maps/map31.h
engines/mm/mm1/maps/map32.cpp
engines/mm/mm1/maps/map32.h
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/maps.cpp
engines/mm/mm1/views/maps/giant.cpp
engines/mm/mm1/views/maps/giant.h
engines/mm/mm1/views/maps/lion.cpp
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index 0774147ec27..82ef1bb9bb1 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -115,6 +115,42 @@ void Map30::special03() {
));
}
+Common::String Map30::worthiness() {
+ Character &c = *g_globals->_currCharacter;
+ if ((c._flags[1] & ~CHARFLAG1_WORTHY) == ~CHARFLAG1_WORTHY)
+ return worthy();
+ else
+ return unworthy();
+}
+
+Common::String Map30::worthy() {
+ Character &c = *g_globals->_currCharacter;
+ int val = ((c._worthiness + 1) / 2) * 256;
+ c._exp += val;
+
+ Common::String line = Common::String::format(
+ STRING["maps.map30.worthy"].c_str(), '0' + (c._worthiness / 5));
+ line = Common::String::format("%s%d %s",
+ line.c_str(), val, STRING["maps.map30.experience"].c_str());
+
+ if (c._worthiness & 0x80) {
+ int attrNum = getRandomNumber(7) - 1;
+ line += Common::String::format(", +3 %s",
+ STRING[Common::String::format("maps.map30.attributes.%d", attrNum)].c_str());
+
+ AttributePair &attrib = c.getAttribute(attrNum);
+ if (attrib._base < 43)
+ attrib._current = attrib._base = attrib._base + 3;
+ }
+
+ c._worthiness = 0;
+ return line;
+}
+
+Common::String Map30::unworthy() {
+ return STRING["maps.map30.unworthy"];
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map30.h b/engines/mm/mm1/maps/map30.h
index 57c4b75f4e8..dccaf2d1a10 100644
--- a/engines/mm/mm1/maps/map30.h
+++ b/engines/mm/mm1/maps/map30.h
@@ -42,6 +42,9 @@ private:
&Map30::special02,
&Map30::special03
};
+
+ Common::String worthy();
+ Common::String unworthy();
public:
Map30() : MapDesert(30, "areae1", 0x112, 2, 137, MapDesert::RND_FULL) {}
@@ -49,6 +52,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Handles worthiness, returning resulting message
+ */
+ Common::String worthiness();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map31.cpp b/engines/mm/mm1/maps/map31.cpp
index e835fb3e026..892e8d1265d 100644
--- a/engines/mm/mm1/maps/map31.cpp
+++ b/engines/mm/mm1/maps/map31.cpp
@@ -46,7 +46,6 @@ void Map31::special() {
}
}
-
if (_walls[g_maps->_mapOffset] != 0xff) {
if (getRandomNumber(100) < 25) {
g_maps->clearSpecial();
@@ -92,7 +91,7 @@ void Map31::special02() {
void Map31::special06() {
if (_data[VAL1]) {
- g_globals->_treasure._items[2] = 243;
+ g_globals->_treasure._items[2] = LASER_BLASTER_ID;
g_events->addAction(KEYBIND_SEARCH);
} else {
none160();
diff --git a/engines/mm/mm1/maps/map31.h b/engines/mm/mm1/maps/map31.h
index e8a499c4160..32a1975559e 100644
--- a/engines/mm/mm1/maps/map31.h
+++ b/engines/mm/mm1/maps/map31.h
@@ -46,7 +46,7 @@ private:
&Map31::special06
};
public:
- Map31() : MapDesert(31, "areae2", 0x706, 3, 80, MapDesert::RND_BASIC) {}
+ Map31() : MapDesert(31, "areae2", 0x706, 2, 80, MapDesert::RND_BASIC) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map32.cpp b/engines/mm/mm1/maps/map32.cpp
index 138f5079906..ec4e25e7ddc 100644
--- a/engines/mm/mm1/maps/map32.cpp
+++ b/engines/mm/mm1/maps/map32.cpp
@@ -88,6 +88,7 @@ void Map32::special02() {
_data[VAL2] = 0;
} else {
+ send("View", DrawGraphicMessage(65 + 6));
send(SoundMessage(
STRING["maps.map32.castle"],
[](const Common::KeyState &ks) {
@@ -95,9 +96,11 @@ void Map32::special02() {
if (ks.keycode == Common::KEYCODE_y) {
g_events->close();
map[VAL2] = 0xff;
+ updateGame();
} else if (ks.keycode == Common::KEYCODE_n) {
g_events->close();
map[VAL2]++;
+ updateGame();
}
}
));
diff --git a/engines/mm/mm1/maps/map32.h b/engines/mm/mm1/maps/map32.h
index b5e007e0c5b..7a8cea67322 100644
--- a/engines/mm/mm1/maps/map32.h
+++ b/engines/mm/mm1/maps/map32.h
@@ -46,7 +46,7 @@ private:
&Map32::special05
};
public:
- Map32() : Map(32, "areae3", 0xb1a, 3) {}
+ Map32() : Map(32, "areae3", 0xb1a, 2) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index bd51ff86e1c..53d3629af28 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -170,12 +170,20 @@ void Map33::special03() {
}
void Map33::special04() {
+ g_maps->clearSpecial();
+
send(SoundMessage(
STRING["maps.map33.corpse"],
[]() {
- g_events->send(SoundMessage(STRING["maps.map33.thanks"]));
- g_globals->_treasure.setGems(50);
- g_events->addAction(KEYBIND_SEARCH);
+ SoundMessage msg(
+ STRING["maps.map33.thanks"],
+ [](const Common::KeyState &) {
+ g_events->close();
+ g_globals->_treasure.setGems(50);
+ g_events->addAction(KEYBIND_SEARCH);
+ }
+ );
+ g_events->send(msg);
}
));
}
diff --git a/engines/mm/mm1/maps/maps.cpp b/engines/mm/mm1/maps/maps.cpp
index 04be2549e78..9d7d50b87a5 100644
--- a/engines/mm/mm1/maps/maps.cpp
+++ b/engines/mm/mm1/maps/maps.cpp
@@ -226,7 +226,6 @@ void Maps::select(uint16 id, byte section) {
_id = id;
_section = section;
-
uint mapId = getIndex(id, section);
load(mapId);
}
diff --git a/engines/mm/mm1/views/maps/giant.cpp b/engines/mm/mm1/views/maps/giant.cpp
index 36db4b9599a..752b4984602 100644
--- a/engines/mm/mm1/views/maps/giant.cpp
+++ b/engines/mm/mm1/views/maps/giant.cpp
@@ -81,40 +81,9 @@ void Giant::charSelected(uint charIndex) {
if (charIndex >= g_globals->_party.size())
return;
- Character &c = g_globals->_party[charIndex];
- g_globals->_currCharacter = &c;
-
- if ((c._flags[1] & ~CHARFLAG1_WORTHY) == ~CHARFLAG1_WORTHY)
- worthy();
- else
- unworthy();
-}
-
-void Giant::timeout() {
- redraw();
-}
-
-void Giant::worthy() {
- Character &c = *g_globals->_currCharacter;
- int val = ((c._worthiness + 1) / 2) * 256;
- c._exp += val;
-
- Common::String line = Common::String::format(
- STRING["maps.map30.worthy"].c_str(), '0' + (c._worthiness / 5));
- line = Common::String::format("%s%d %s",
- line.c_str(), val, STRING["maps.map30.experience"].c_str());
-
- if (c._worthiness & 0x80) {
- int attrNum = getRandomNumber(7) - 1;
- line += Common::String::format(", +3 %s",
- STRING[Common::String::format("maps.map30.attributes.%d", attrNum)].c_str());
-
- AttributePair &attrib = c.getAttribute(attrNum);
- if (attrib._base < 43)
- attrib._current = attrib._base = attrib._base + 3;
- }
-
- c._worthiness = 0;
+ MM1::Maps::Map30 &map = *static_cast<MM1::Maps::Map30 *>(g_maps->_currentMap);
+ g_globals->_currCharacter = &g_globals->_party[charIndex];
+ Common::String line = map.worthiness();
clearSurface();
writeString(0, 1, line);
@@ -123,12 +92,8 @@ void Giant::worthy() {
delaySeconds(5);
}
-void Giant::unworthy() {
- clearSurface();
- writeString(0, 1, STRING["maps.map30.unworthy"]);
- Sound::sound(SOUND_2);
-
- delaySeconds(5);
+void Giant::timeout() {
+ redraw();
}
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/giant.h b/engines/mm/mm1/views/maps/giant.h
index 060fbf84dda..f6608c49257 100644
--- a/engines/mm/mm1/views/maps/giant.h
+++ b/engines/mm/mm1/views/maps/giant.h
@@ -32,8 +32,7 @@ namespace Maps {
class Giant : public TextView {
private:
void charSelected(uint charIndex);
- void worthy();
- void unworthy();
+
public:
Giant();
virtual ~Giant() {}
diff --git a/engines/mm/mm1/views/maps/lion.cpp b/engines/mm/mm1/views/maps/lion.cpp
index 2e787f62953..20cdae91e70 100644
--- a/engines/mm/mm1/views/maps/lion.cpp
+++ b/engines/mm/mm1/views/maps/lion.cpp
@@ -42,6 +42,7 @@ void Lion::draw() {
void Lion::answerEntered() {
MM1::Maps::Map32 &map = *static_cast<MM1::Maps::Map32 *>(g_maps->_currentMap);
+ close();
map.passwordEntered(_answer);
}
Commit: 16b25033db100da73c2d2f7f6a3c8e27e76f936b
https://github.com/scummvm/scummvm/commit/16b25033db100da73c2d2f7f6a3c8e27e76f936b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: Fix multiple maps' special loop
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map00.cpp
engines/mm/mm1/maps/map02.cpp
engines/mm/mm1/maps/map04.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map08.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map12.cpp
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/maps/map29.cpp
engines/mm/mm1/maps/map34.cpp
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map40.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map54.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index beefdc164b1..361a6e15db6 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1422,7 +1422,7 @@ maps:
map35:
exit: "EXIT CASTLE, (Y/N)?"
- guards: "CASTLE GUARDS EXCLAIM\n""NO MERCHANTS PASS! BEGONE PEASANTS."""
+ merchant_pass: "CASTLE GUARDS EXCLAIM\n""NO MERCHANTS PASS! BEGONE PEASANTS."""
quests:
0: "FIND THE ANCIENT RUINS IN THE\nQUIVERING FOREST"
1: "VISIT BLITHES PEAK, AND REPORT"
diff --git a/engines/mm/mm1/maps/map00.cpp b/engines/mm/mm1/maps/map00.cpp
index efb9b82b7c9..4609716f8a3 100644
--- a/engines/mm/mm1/maps/map00.cpp
+++ b/engines/mm/mm1/maps/map00.cpp
@@ -38,7 +38,7 @@ namespace Maps {
void Map00::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 24; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
diff --git a/engines/mm/mm1/maps/map02.cpp b/engines/mm/mm1/maps/map02.cpp
index 5c03ae1ea9b..9b8428a4b31 100644
--- a/engines/mm/mm1/maps/map02.cpp
+++ b/engines/mm/mm1/maps/map02.cpp
@@ -41,7 +41,6 @@ void Map02::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[73 + i]) {
-
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map04.cpp b/engines/mm/mm1/maps/map04.cpp
index a2260a3ecf0..08770adc042 100644
--- a/engines/mm/mm1/maps/map04.cpp
+++ b/engines/mm/mm1/maps/map04.cpp
@@ -36,7 +36,6 @@ void Map04::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[73 + i]) {
-
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index e1ff7c66f97..6c93eff53ea 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -41,7 +41,6 @@ void Map07::special() {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[69 + i]) {
-
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map08.cpp b/engines/mm/mm1/maps/map08.cpp
index 5e4d3593c2e..8d3d18e5811 100644
--- a/engines/mm/mm1/maps/map08.cpp
+++ b/engines/mm/mm1/maps/map08.cpp
@@ -39,7 +39,7 @@ static const byte OFFSETS2[8] = { 130, 82, 134, 86, 137, 89, 141, 93 };
void Map08::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 24; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index a652f150f64..4ace9050aea 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -45,12 +45,11 @@ static const byte MAP_DEST_SECTION[15] = {
void Map10::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 34; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
if (g_maps->_forwardMask & _data[85 + i]) {
-
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map12.cpp b/engines/mm/mm1/maps/map12.cpp
index 1af1afe7829..7e89bd2df32 100644
--- a/engines/mm/mm1/maps/map12.cpp
+++ b/engines/mm/mm1/maps/map12.cpp
@@ -34,7 +34,7 @@ namespace Maps {
void Map12::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 18; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index ebe24573497..37b449d61fa 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -37,7 +37,7 @@ void Map24::special() {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[65 + i]) {
+ if (g_maps->_forwardMask & _data[61 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
index d3826b6829a..da6b33f4140 100644
--- a/engines/mm/mm1/maps/map29.cpp
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -40,7 +40,7 @@ void Map29::special() {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[55 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
diff --git a/engines/mm/mm1/maps/map34.cpp b/engines/mm/mm1/maps/map34.cpp
index b9e90d28110..d3a52e68b8c 100644
--- a/engines/mm/mm1/maps/map34.cpp
+++ b/engines/mm/mm1/maps/map34.cpp
@@ -33,7 +33,7 @@ namespace Maps {
void Map34::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 23; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
@@ -80,8 +80,8 @@ void Map34::special02() {
Sound::sound2(SOUND_2);
InfoMessage msg(
- 0, 0, STRING["alamar1"],
- 0, 7, STRING["alamar2"]
+ 0, 0, STRING["maps.map34.alamar1"],
+ 0, 7, STRING["maps.map34.alamar2"]
);
msg._largeMessage = true;
send(msg);
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index 91c005d67a0..b4af09cb782 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -93,7 +93,7 @@ void Map35::special03() {
void Map35::special04() {
if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
- send(SoundMessage(STRING["maps.map35.merchants"]));
+ send(SoundMessage(STRING["maps.map35.merchant_pass"]));
g_maps->_mapPos.y++;
updateGame();
}
diff --git a/engines/mm/mm1/maps/map40.cpp b/engines/mm/mm1/maps/map40.cpp
index edb6df12ca1..c1256ba929f 100644
--- a/engines/mm/mm1/maps/map40.cpp
+++ b/engines/mm/mm1/maps/map40.cpp
@@ -35,7 +35,7 @@ namespace Maps {
void Map40::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 23; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 38a89e8ce49..03bb4138240 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -43,7 +43,7 @@ static const uint16 QUEST_EXPERIENCE[7] = {
void Map43::special() {
// Scan for special actions on the map cell
- for (uint i = 0; i < _data[50]; ++i) {
+ for (uint i = 0; i < 9; ++i) {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index c102fc9fcaf..764af642b79 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -40,7 +40,7 @@ void Map54::special() {
if (g_maps->_mapOffset == _data[51 + i]) {
// Found a specially handled cell, but it
// only triggers in designated direction(s)
- if (g_maps->_forwardMask & _data[75 + i]) {
+ if (g_maps->_forwardMask & _data[59 + i]) {
(this->*SPECIAL_FN[i])();
} else {
checkPartyDead();
Commit: 3cacb37d3b0d658db4504a3b7738ba2e08b88304
https://github.com/scummvm/scummvm/commit/3cacb37d3b0d658db4504a3b7738ba2e08b88304
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: Fix Inspectron and Hacker views
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map35.cpp
engines/mm/mm1/maps/map36.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/maps/hacker.cpp
engines/mm/mm1/views/maps/hacker.h
engines/mm/mm1/views/maps/inspectron.cpp
engines/mm/mm1/views/maps/inspectron.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 361a6e15db6..838a2b36e90 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1432,7 +1432,7 @@ maps:
5: "SOLVE THE RIDDLE OF THE RUBY"
6: "DEFEAT THE STRONGHOLD\nIN THE ENCHANTED FOREST"
inspectron1: "LORD INSPECTRON SPEAKS:\n"
- inspectron2: """YOUR SERVICES ARE NEEDED!"" ACCEPT (Y/N)?"
+ inspectron2: """YOUR SERVICES ARE NEEDED!""ACCEPT (Y/N)?"
inspectron3: """RETURN NOT UNTIL THY QUEST IS COMPLETE"""
inspectron4: """SORRY, BUT SINCE YOU ARE CURRENTLY\nQUESTED, I CAN'T ENGAGE YOUR SERVICES."""
inspectron5: "WELL DONE, QUEST COMPLETE! +%u EXP"
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index b4af09cb782..ac0ce99ee18 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -102,7 +102,7 @@ void Map35::special04() {
void Map35::special05() {
updateFlags();
send("View", DrawGraphicMessage(7 + 65));
- g_events->addView("Inspectron");
+ send("Inspectron", GameMessage("DISPLAY"));
}
void Map35::special06() {
@@ -174,7 +174,7 @@ void Map35::acceptQuest() {
Common::String Map35::checkQuestComplete() {
Character &leader = g_globals->_party[0];
- int qIndex = leader._quest - 7;
+ int qIndex = leader._quest - 8;
if (leader._flags[5] & MATCH_FLAGS[qIndex] & 0x7f) {
// The quest was complete
diff --git a/engines/mm/mm1/maps/map36.cpp b/engines/mm/mm1/maps/map36.cpp
index e388afd094f..c793b944ecc 100644
--- a/engines/mm/mm1/maps/map36.cpp
+++ b/engines/mm/mm1/maps/map36.cpp
@@ -99,7 +99,7 @@ void Map36::special04() {
void Map36::special05() {
updateFlags();
send("View", DrawGraphicMessage(7 + 65));
- g_events->addView("Hacker");
+ send("Hacker", GameMessage("DISPLAY"));
}
void Map36::special06() {
@@ -145,36 +145,46 @@ void Map36::updateFlags() {
void Map36::acceptQuest() {
Character &leader = g_globals->_party[0];
- byte flags = leader._flags[8];
+ byte flags = leader._flags[9];
// Find quest that hasn't been done yet
int questNum;
- for (questNum = 8; flags && questNum < 15; ++questNum, flags >>= 1) {
+ for (questNum = 15; flags && questNum < 22; ++questNum, flags >>= 1) {
if (!(flags & 1))
break;
}
- if (questNum == 15) {
+ if (questNum == 22) {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
- c._flags[8] = CHARFLAG8_80;
- c._flags[5] = CHARFLAG5_80;
+ c._flags[9] = CHARFLAG9_80;
+ c._flags[6] = CHARFLAG6_80;
+ c._backpack.empty();
}
- }
- // Assign the quest to all party characters
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- c._quest = questNum;
- }
+ send(SoundMessage(
+ STRING["maps.map36.hacker7"],
+ [](const Common::KeyState &) {
+ g_maps->_mapPos = Common::Point(11, 15);
+ g_maps->_currentMap->updateGame();
+ }
+ ));
- // Draw the scene
- g_maps->_mapPos.y++;
- redrawGame();
+ } else {
+ // Assign the quest to all party characters
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = questNum;
+ }
+
+ // Draw the scene
+ g_maps->_mapPos.y++;
+ redrawGame();
+ }
}
Common::String Map36::checkQuestComplete() {
Character &leader = g_globals->_party[0];
- int qIndex = leader._quest - 14;
+ int qIndex = leader._quest - 15;
if (leader._flags[6] & MATCH_FLAGS[qIndex] & 0x7f) {
// The quest was complete
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 19331a9c2ed..2afc8e72062 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -57,6 +57,7 @@
#include "mm/mm1/views/maps/ghost.h"
#include "mm/mm1/views/maps/giant.h"
#include "mm/mm1/views/maps/gypsy.h"
+#include "mm/mm1/views/maps/hacker.h"
#include "mm/mm1/views/maps/ice_princess.h"
#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/views/maps/keeper.h"
@@ -125,6 +126,7 @@ private:
Views::Maps::Ghost _ghost;
Views::Maps::Giant _giant;
Views::Maps::Gypsy _gypsy;
+ Views::Maps::Hacker _hacker;
Views::Maps::IcePrincess _icePrincess;
Views::Maps::Inspectron _inspectron;
Views::Maps::Keeper _keeper;
diff --git a/engines/mm/mm1/views/maps/hacker.cpp b/engines/mm/mm1/views/maps/hacker.cpp
index 41be8170dfc..a6e8202ff08 100644
--- a/engines/mm/mm1/views/maps/hacker.cpp
+++ b/engines/mm/mm1/views/maps/hacker.cpp
@@ -22,6 +22,7 @@
#include "mm/mm1/views/maps/hacker.h"
#include "mm/mm1/maps/map36.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -32,26 +33,24 @@ Hacker::Hacker() : TextView("Hacker") {
_bounds = getLineBounds(20, 24);
}
-bool Hacker::msgFocus(const FocusMessage &msg) {
+bool Hacker::msgGame(const GameMessage &msg) {
+ if (msg._name != "DISPLAY")
+ return false;
+
g_globals->_currCharacter = &g_globals->_party[0];
_canAccept = !g_globals->_currCharacter->_quest;
- return TextView::msgFocus(msg);
-}
-
-void Hacker::draw() {
- MM1::Maps::Map36 &map = *static_cast<MM1::Maps::Map36 *>(g_maps->_currentMap);
- clearSurface();
if (_canAccept) {
- send(SoundMessage(
- 0, 1, STRING["maps.map36.hacker1"],
- 0, 2, STRING["maps.map36.hacker2"]
- ));
+ // Show the view
+ Sound::sound(SOUND_2);
+ addView();
+
} else {
+ MM1::Maps::Map36 &map = *static_cast<MM1::Maps::Map36 *>(g_maps->_currentMap);
int questNum = g_globals->_party[0]._quest;
Common::String line;
- if (questNum >= 15 || questNum <= 21)
+ if (questNum >= 15 && questNum <= 21)
line = map.checkQuestComplete();
else
line = STRING["maps.map36.hacker4"];
@@ -59,33 +58,41 @@ void Hacker::draw() {
g_maps->_mapPos.x--;
map.redrawGame();
- clearSurface();
send(SoundMessage(
0, 1, STRING["maps.map36.hacker1"],
0, 2, line
));
- close();
}
+
+ return true;
+}
+
+void Hacker::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map36.hacker1"]);
+ writeString(0, 2, STRING["maps.map36.hacker2"]);
}
bool Hacker::msgKeypress(const KeypressMessage &msg) {
MM1::Maps::Map36 &map = *static_cast<MM1::Maps::Map36 *>(g_maps->_currentMap);
- if (_canAccept) {
- if (msg.keycode == Common::KEYCODE_y) {
- map.acceptQuest();
-
- clearSurface();
- writeString(0, 1, STRING["maps.map36.hacker1"]);
- writeString(0, 2, STRING[Common::String::format(
- "maps.map36.ingredients.%d",
- g_globals->_party[0]._quest)]);
- close();
-
- } else if (msg.keycode == Common::KEYCODE_n) {
- close();
- map.redrawGame();
+ if (msg.keycode == Common::KEYCODE_y) {
+ close();
+ map.acceptQuest();
+
+ Character &c = g_globals->_party[0];
+ if (c._quest) {
+ send(InfoMessage(
+ 0, 1, STRING["maps.map36.hacker1"],
+ 0, 2, STRING[Common::String::format(
+ "maps.map36.ingredients.%d",
+ g_globals->_party[0]._quest - 15)]
+ ));
}
+
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ map.redrawGame();
}
return true;
diff --git a/engines/mm/mm1/views/maps/hacker.h b/engines/mm/mm1/views/maps/hacker.h
index 020242a7364..34452f0a525 100644
--- a/engines/mm/mm1/views/maps/hacker.h
+++ b/engines/mm/mm1/views/maps/hacker.h
@@ -36,7 +36,7 @@ public:
Hacker();
virtual ~Hacker() {}
- bool msgFocus(const FocusMessage &msg) override;
+ bool msgGame(const GameMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
diff --git a/engines/mm/mm1/views/maps/inspectron.cpp b/engines/mm/mm1/views/maps/inspectron.cpp
index 5d969451527..706bbb8c568 100644
--- a/engines/mm/mm1/views/maps/inspectron.cpp
+++ b/engines/mm/mm1/views/maps/inspectron.cpp
@@ -22,6 +22,7 @@
#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/maps/map35.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -35,26 +36,26 @@ Inspectron::Inspectron() : TextView("Inspectron") {
_bounds = getLineBounds(20, 24);
}
-bool Inspectron::msgFocus(const FocusMessage &msg) {
+bool Inspectron::msgGame(const GameMessage &msg) {
+ if (msg._name != "DISPLAY")
+ return false;
+
g_globals->_currCharacter = &g_globals->_party[0];
_canAccept = !g_globals->_currCharacter->_quest;
- return TextView::msgFocus(msg);
-}
-
-void Inspectron::draw() {
- MM1::Maps::Map35 &map = *static_cast<MM1::Maps::Map35 *>(g_maps->_currentMap);
- clearSurface();
if (_canAccept) {
- send(SoundMessage(
- 0, 1, STRING["maps.map35.inspectron1"],
- 0, 2, STRING["maps.map35.inspectron2"]
- ));
+ // Open the view for display
+ Sound::sound(SOUND_2);
+ addView();
+
} else {
+ // There's an active quest, so any result will simply be
+ // displayed as a game message
+ MM1::Maps::Map35 &map = *static_cast<MM1::Maps::Map35 *>(g_maps->_currentMap);
int questNum = g_globals->_party[0]._quest;
Common::String line;
- if (questNum >= 8 || questNum <= 14)
+ if (questNum >= 8 && questNum <= 14)
line = map.checkQuestComplete();
else
line = STRING["maps.map35.inspectron4"];
@@ -62,33 +63,39 @@ void Inspectron::draw() {
g_maps->_mapPos.y++;
map.redrawGame();
- clearSurface();
send(SoundMessage(
0, 1, STRING["maps.map35.inspectron1"],
0, 2, line
));
- close();
}
+
+ return true;
+}
+
+void Inspectron::draw() {
+ clearSurface();
+ writeString(0, 1, STRING["maps.map35.inspectron1"]);
+ writeString(0, 2, STRING["maps.map35.inspectron2"]);
}
bool Inspectron::msgKeypress(const KeypressMessage &msg) {
MM1::Maps::Map35 &map = *static_cast<MM1::Maps::Map35 *>(g_maps->_currentMap);
- if (_canAccept) {
- if (msg.keycode == Common::KEYCODE_y) {
- map.acceptQuest();
+ if (msg.keycode == Common::KEYCODE_y) {
+ map.acceptQuest();
+ close();
- clearSurface();
- writeString(0, 1, STRING["maps.map35.inspectron1"]);
- writeString(0, 2, STRING[Common::String::format(
+ send(InfoMessage(
+ 0, 1, STRING["maps.map35.inspectron1"],
+ 0, 2, STRING[Common::String::format(
"maps.map35.quests.%d",
- g_globals->_party[0]._quest)]);
- close();
+ g_globals->_party[0]._quest - 8
+ )]
+ ));
- } else if (msg.keycode == Common::KEYCODE_n) {
- close();
- map.redrawGame();
- }
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ map.redrawGame();
}
return true;
diff --git a/engines/mm/mm1/views/maps/inspectron.h b/engines/mm/mm1/views/maps/inspectron.h
index 257d863e691..e951267f3e3 100644
--- a/engines/mm/mm1/views/maps/inspectron.h
+++ b/engines/mm/mm1/views/maps/inspectron.h
@@ -36,7 +36,7 @@ public:
Inspectron();
virtual ~Inspectron() {}
- bool msgFocus(const FocusMessage &msg) override;
+ bool msgGame(const GameMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
};
Commit: 2f9c787e5fd217d8830910dbb941bb75da7d8b7c
https://github.com/scummvm/scummvm/commit/2f9c787e5fd217d8830910dbb941bb75da7d8b7c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: Map fixes
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map37.h
engines/mm/mm1/maps/map40.cpp
engines/mm/mm1/maps/map41.cpp
engines/mm/mm1/maps/map42.cpp
engines/mm/mm1/views/maps/dog_statue.cpp
engines/mm/mm1/views/maps/ghost.cpp
engines/mm/mm1/views/maps/ruby.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 838a2b36e90..3ba9af9e7a6 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1482,7 +1482,7 @@ maps:
map39:
message6: "ETCHED IN GOLD, MESSAGE 6 READS:\nBOOK-DONE.-A-SELF-THAT-FROM-KEY-YOU-\nBE-TO-SEEMS"
- ruby1: "IN THE CENTER OF THE ROOM, A HUGE RUBY\nSTANDS ATOP A PEDESTAL. HEXAGONALLY\nSHAPED, IT GLOWS RHYTHMICALLY!\nMESMERIZED BY ITS LIGHT, YOU HEAR:\nGLASS THAT GLITTERS, RUBIES THAT GLOW\nWHEN I TWINKLE, I CAST A RAINBOW\nWHAT AM I? :\n> ..............."
+ ruby1: "IN THE CENTER OF THE ROOM, A HUGE RUBY\nSTANDS ATOP A PEDESTAL. HEXAGONALLY\nSHAPED, IT GLOWS RHYTHMICALLY!\nMESMERIZED BY ITS LIGHT, YOU HEAR:\nGLASS THAT GLITTERS, RUBIES THAT GLOW\nWHEN I TWINKLE, I CAST A RAINBOW\nWHAT AM I? :> ..............."
ruby2: "WRONG! A BRIGHT FLASH..."
door_repels: "A SILVER DOOR REPELS YOU!"
door_glows: "A SILVER DOOR, YOUR SILVER KEY GLOWS!"
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 178926179e4..6f574e24ed5 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -101,6 +101,7 @@ protected:
uint _mapIndex;
byte _defaultSection;
Common::Array<byte> _data;
+ bool _mappingAllowed = true;
private:
/**
* Loads the map's maze data
@@ -166,6 +167,15 @@ public:
return _defaultSection;
}
+ /**
+ * Returns true if mapping is allowed in enhanced mode.
+ * This is to prevent places like the desert where the
+ * players shouldn't be able to see where they are
+ */
+ bool mappingAllowed() const {
+ return _mappingAllowed;
+ }
+
/**
* Accesses the map data
*/
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index 9d088725619..ad1e6fcb688 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -46,12 +46,12 @@ void Map37::special() {
}
}
- if (g_events->isKeypressPending()) {
- send(InfoMessage());
- } else {
- send(SoundMessage(STRING["maps.map37.spins"]));
- g_events->addAction(KEYBIND_TURN_LEFT);
- }
+ // Randomly spin the party
+ int count = getRandomNumber(4) - 1;
+ for (int i = 0; i < count; ++i)
+ g_maps->turnLeft();
+
+ send(SoundMessage(STRING["maps.map37.spins"]));
}
void Map37::special00() {
@@ -96,6 +96,7 @@ void Map37::special03() {
void Map37::special04() {
Game::Encounter &enc = g_globals->_encounters;
+ g_maps->clearSpecial();
if (_data[VAL1]) {
g_events->addView("Ghost");
diff --git a/engines/mm/mm1/maps/map37.h b/engines/mm/mm1/maps/map37.h
index cb7d3e378e0..c768696aea6 100644
--- a/engines/mm/mm1/maps/map37.h
+++ b/engines/mm/mm1/maps/map37.h
@@ -73,7 +73,9 @@ private:
&Map37::special19
};
public:
- Map37() : Map(37, "qvl1", 0xf03, 3) {}
+ Map37() : Map(37, "qvl1", 0xf03, 3) {
+ _mappingAllowed = false;
+ }
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map40.cpp b/engines/mm/mm1/maps/map40.cpp
index c1256ba929f..2db0c2c8cad 100644
--- a/engines/mm/mm1/maps/map40.cpp
+++ b/engines/mm/mm1/maps/map40.cpp
@@ -185,10 +185,11 @@ void Map40::archerResist() {
}
void Map40::archerSubmit() {
+ // As long as even one character has gold, Archer will take
+ // all of the party's gold. However, if the party is penniless,
+ // then Archer will actually give each character 5000 gold
for (uint i = 0; i < g_globals->_party.size(); ++i) {
if (g_globals->_party[i]._gold) {
- // As long as even one character has gold, Archer
- // will take all of the party's gold
WRITE_LE_UINT16(&_data[GOLD], 0);
break;
}
diff --git a/engines/mm/mm1/maps/map41.cpp b/engines/mm/mm1/maps/map41.cpp
index 438aa451e70..d4774e2accb 100644
--- a/engines/mm/mm1/maps/map41.cpp
+++ b/engines/mm/mm1/maps/map41.cpp
@@ -48,14 +48,14 @@ void Map41::special() {
}
void Map41::special00() {
- send(SoundMessage(STRING["maps.map40.message3"]));
+ send(SoundMessage(STRING["maps.map41.message3"]));
}
void Map41::special01() {
visitedExit();
send(SoundMessage(
- STRING["maps.maps40.stairs_up"],
+ STRING["maps.map41.stairs_up"],
[]() {
g_maps->_mapPos = Common::Point(14, 2);
g_maps->changeMap(0x101, 2);
@@ -79,7 +79,7 @@ void Map41::special03() {
}
void Map41::special04() {
- send(SoundMessage(STRING["maps.map40.dung"]));
+ send(SoundMessage(STRING["maps.map41.dung"]));
}
void Map41::special05() {
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
index 442e6f6edb7..74f261a4b6e 100644
--- a/engines/mm/mm1/maps/map42.cpp
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -52,11 +52,11 @@ void Map42::special() {
}
void Map42::special00() {
- g_events->addView("WhiteDog");
+ g_events->addView("DogStatue");
}
void Map42::special01() {
- send(SoundMessage(STRING["maps.map42.message4"]));
+ send(SoundMessage(STRING["maps.map42.message9"]));
}
void Map42::special02() {
@@ -88,11 +88,9 @@ void Map42::special03() {
void Map42::special04() {
Sound::sound(SOUND_2);
- g_maps->_mapPos.x++;
- if (g_maps->_mapPos.x >= 10)
- g_maps->_mapPos.x = 6;
- updateGame();
+ g_maps->_mapPos.x = getRandomNumber(5) + 5;
+ redrawGame();
}
void Map42::special05() {
diff --git a/engines/mm/mm1/views/maps/dog_statue.cpp b/engines/mm/mm1/views/maps/dog_statue.cpp
index 6ff6d7310e0..b6d0af9ad49 100644
--- a/engines/mm/mm1/views/maps/dog_statue.cpp
+++ b/engines/mm/mm1/views/maps/dog_statue.cpp
@@ -70,7 +70,6 @@ bool DogStatue::msgKeypress(const KeypressMessage &msg) {
close();
if (msg.keycode == Common::KEYCODE_y) {
- close();
map.dogDesecrate();
} else {
close();
diff --git a/engines/mm/mm1/views/maps/ghost.cpp b/engines/mm/mm1/views/maps/ghost.cpp
index 2c25d54825e..65db2831ec8 100644
--- a/engines/mm/mm1/views/maps/ghost.cpp
+++ b/engines/mm/mm1/views/maps/ghost.cpp
@@ -38,7 +38,7 @@ Ghost::Ghost() : TextView("Ghost") {
void Ghost::draw() {
clearSurface();
- writeString(0, 1, STRING["maps.map37.okram1"]);
+ writeString(0, 1, STRING["maps.map37.okrim1"]);
}
bool Ghost::msgKeypress(const KeypressMessage &msg) {
@@ -49,12 +49,14 @@ bool Ghost::msgKeypress(const KeypressMessage &msg) {
g_globals->_party[0]._condition = ERADICATED;
} else {
clearSurface();
- writeString(0, 1, STRING["maps.map37.okram2"]);
+ writeString(0, 1, STRING["maps.map37.okrim2"]);
map[MM1::Maps::MAP_29] = 32;
map[MM1::Maps::MAP_47] = 8;
}
+ // Note: You get the ring whether or not you agree to it.
+ // This is indeed how the original's logic is implemented
close();
g_globals->_treasure._items[2] = RING_OF_OKRIM_ID;
g_events->addAction(KEYBIND_SEARCH);
diff --git a/engines/mm/mm1/views/maps/ruby.cpp b/engines/mm/mm1/views/maps/ruby.cpp
index ef4eca42061..2489644905a 100644
--- a/engines/mm/mm1/views/maps/ruby.cpp
+++ b/engines/mm/mm1/views/maps/ruby.cpp
@@ -22,6 +22,7 @@
#include "mm/mm1/views/maps/ruby.h"
#include "mm/mm1/maps/map39.h"
#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
namespace MM {
namespace MM1 {
@@ -30,7 +31,7 @@ namespace Maps {
#define ANSWER_OFFSET 477
-Ruby::Ruby() : AnswerEntry("Ruby", Common::Point(2, 9), 12) {
+Ruby::Ruby() : AnswerEntry("Ruby", Common::Point(14, 7), 12) {
_bounds = getLineBounds(17, 24);
}
@@ -49,19 +50,22 @@ void Ruby::answerEntered() {
properAnswer += map[ANSWER_OFFSET + i] - 64;
if (_answer.equalsIgnoreCase(properAnswer)) {
+ g_maps->clearSpecial();
+ Sound::sound(SOUND_3);
+ map.redrawGame();
+
for (uint i = 0; i < g_globals->_party.size(); ++i) {
g_globals->_party[i]._flags[5] |= CHARFLAG5_20;
}
+ g_globals->_treasure._items[2] = CRYSTAL_KEY_ID;
g_events->addAction(KEYBIND_SEARCH);
} else {
g_maps->_mapPos.x = 9;
map.updateGame();
- clearSurface();
- writeString(0, 1, STRING["maps.map39.ruby2"]);
- close();
+ send(InfoMessage(STRING["maps.map39.ruby2"]));
}
}
Commit: 17042d1f18e80043174453b0e6650be7e0494d1b
https://github.com/scummvm/scummvm/commit/17042d1f18e80043174453b0e6650be7e0494d1b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:47+01:00
Commit Message:
MM: MM1: Fixes for remaining maps
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/maps/map43.h
engines/mm/mm1/maps/map46.h
engines/mm/mm1/maps/map48.cpp
engines/mm/mm1/maps/map48.h
engines/mm/mm1/maps/map49.cpp
engines/mm/mm1/maps/map51.cpp
engines/mm/mm1/maps/map53.cpp
engines/mm/mm1/maps/map54.cpp
engines/mm/mm1/maps/map54.h
engines/mm/mm1/views/maps/alamar.cpp
engines/mm/mm1/views/maps/dog_statue.cpp
engines/mm/mm1/views/maps/keeper.cpp
engines/mm/mm1/views/maps/orango.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 3ba9af9e7a6..e49d3ffe716 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1517,7 +1517,7 @@ maps:
message9: "ETCHED IN GOLD, MESSAGE 9 READS:\nSUCCESSFUL-THAT-TRAINING,-THE-WORTHY-\nTHE-VISIT-YET-INNER-REALITY,-ORDER,"
defeated: "THE MASTER OF THIS STRONGHOLD\nHAS BEEN DEFEATED!"
sign1: "ENTER THE MAZE OF THE MINOTAUR...\nIF YOU DARE!"
- statue1: "STANDING ATOP A PEDESTAL IN THE CENTER\nOF THE ROOM IS A STATUE OF A SMALL SABLEAND WHITE DOG. "
+ statue1: "STANDING ATOP A PEDESTAL IN THE CENTER\nOF THE ROOM IS A STATUE OF A SMALL SABLE\nAND WHITE DOG. "
statue2: "IT COMES TO LIFE AND\nSPEAKS,""CONGRATULATIONS, YOU'VE\nCOMPLETED A MAJOR QUEST (+10000 EXP)\nREMEMBER B.J.!"""
statue3: "DESECRATE IT (Y/N)?"
@@ -1534,13 +1534,13 @@ maps:
message_b: "ETCHED IN SILVER, MESSAGE B READS:\nRSTIA-,E1,;/11RN;/M-"
guards: "CASTLE GUARDS EXCLAIM,\n""NO MERCHANTS PASS! BEGONE PEASANTS."""
quests:
- 0: "FIND THE STRONGHOLD IN RAVENS WOOD"
- 1: "FIND LORD KILBURN"
- 2: "DISCOVER THE SECRET OF PORTSMITH"
- 3: "FIND THE PIRATES SECRET COVE"
- 4: "FIND THE SHIPWRECK OF THE JOLLY RAVEN"
- 5: "DEFEAT THE PIRATE GHOST SHIP ANARCHIST"
- 6: "DEFEAT THE STRONGHOLD IN RAVENS WOOD"
+ 1: "FIND THE STRONGHOLD IN RAVENS WOOD"
+ 2: "FIND LORD KILBURN"
+ 3: "DISCOVER THE SECRET OF PORTSMITH"
+ 4: "FIND THE PIRATES SECRET COVE"
+ 5: "FIND THE SHIPWRECK OF THE JOLLY RAVEN"
+ 6: "DEFEAT THE PIRATE GHOST SHIP ANARCHIST"
+ 7: "DEFEAT THE STRONGHOLD IN RAVENS WOOD"
map44:
exit: "A PASSAGE LEADS OUTSIDE, TAKE IT (Y/N)?"
@@ -1567,9 +1567,9 @@ maps:
message5: "ETCHED IN GOLD, MESSAGE 5 READS:\nSCOOP:-THE-DISCOVERIES-YOUR-TO-RETURN-\nTHE-YOUR-FOR-DREAMS-IS"
gong: "COVERED WITH CRYPTIC SYMBOLS, A LARGE\nBRASS GONG HANGS FROM THE CEILING.\nSTRIKE IT (Y/N)?"
tones:
- 0: "A LOUD TONE RESOUNDS\nTHROUGHOUT THE ROOM!"
- 1: "A SHARP TONE ASSAULTS YOUR SENSES!"
- 2: "A MELLOW TONE RELAXES YOU."
+ 1: "A LOUD TONE RESOUNDS\nTHROUGHOUT THE ROOM!"
+ 2: "A SHARP TONE ASSAULTS YOUR SENSES!"
+ 3: "A MELLOW TONE RELAXES YOU."
clerics1: "THE CLERICS OF THE SOUTH SPEAK:\n"
clerics2: """HEAR THE 3 TONES AND RETURN!"""
clerics3: """WE DEEM YOU WORTHY OF ADVANCEMENT!"""
@@ -1578,7 +1578,7 @@ maps:
door_number: "DOOR NUMBER %c"
map48:
- orango1: "A STRANGE ALIEN BEING IN A SHIMMERING\nSILVER JUMPSUIT PROCLAIMS, ""THIS IS A\nSOUL MAZE AND YOU ARE ITS PRISONER!\nTO ESCAPE, YOU MUST FIND YOUR CAPTOR'S\nNAME HIDDEN WITHIN THESE WALLS.""\n\nANSWER:> ..............."
+ orango1: "A STRANGE ALIEN BEING IN A SHIMMERING\nSILVER JUMPSUIT PROCLAIMS, ""THIS IS A\nSOUL MAZE AND YOU ARE ITS PRISONER!\nTO ESCAPE, YOU MUST FIND YOUR CAPTOR'S\nNAME HIDDEN WITHIN THESE WALLS.""\n\nANSWER:>"
orango2: "KEEP LOOKING!"
orango3: "AGENT ORANGO SEVENTEEN REPORTING:\nIMPOSTER XX21A7-3 VOIDED!\nSTARPHASE 5281.6 AT 120-VARN-161 POD #41YOU ARE NOW RANK 1 AND ELIGIBLE FOR\nTRANSFER. FIND INNER SANCTUM FOR NEW\nASSIGNMENT. THE WALLS BEGIN TO FADE...\n(PRESS SPACE)"
@@ -1620,7 +1620,7 @@ maps:
ladder: "A LADDER GOING UP, CLIMB IT (Y/N)?"
map54:
- projector: "ASTRAL PROJECTOR # %c , ZAP!"
+ projector: "ASTRAL PROJECTOR # %c, ZAP!"
slot1: "THERE'S A SMALL SLOT IN THE DOOR.\n"
slot2: "NO ADMITTANCE!"
slot3: "KEY CARD IS REJECTED!"
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index 03bb4138240..b2e8a85ab28 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -101,7 +101,7 @@ void Map43::special04() {
if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
send(SoundMessage(
STRING["maps.map43.guards"],
- [](const Common::KeyState &ks) {
+ [](const Common::KeyState &) {
g_events->focusedView()->close();
g_maps->_mapPos = Common::Point(9, 13);
g_maps->changeMap(0x101, 2);
diff --git a/engines/mm/mm1/maps/map43.h b/engines/mm/mm1/maps/map43.h
index bb06b6b8d80..feb5ae0f746 100644
--- a/engines/mm/mm1/maps/map43.h
+++ b/engines/mm/mm1/maps/map43.h
@@ -54,7 +54,7 @@ private:
&Map43::special08
};
public:
- Map43() : Map(43, "whitew", 0xa11, 1) {}
+ Map43() : Map(43, "whitew", 0xa11, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map46.h b/engines/mm/mm1/maps/map46.h
index e1ee8b47fbb..f0c4df7b16e 100644
--- a/engines/mm/mm1/maps/map46.h
+++ b/engines/mm/mm1/maps/map46.h
@@ -49,7 +49,7 @@ private:
&Map46::special06
};
public:
- Map46() : Map(46, "udrag2", 0xa00, 2) {}
+ Map46() : Map(46, "udrag2", 0xa00, 3) {}
/**
* Handles all special stuff that happens on the map
diff --git a/engines/mm/mm1/maps/map48.cpp b/engines/mm/mm1/maps/map48.cpp
index 19948effa57..a2e205c2c65 100644
--- a/engines/mm/mm1/maps/map48.cpp
+++ b/engines/mm/mm1/maps/map48.cpp
@@ -29,10 +29,34 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define ANSWER_OFFSET 274
+
void Map48::special() {
g_events->addView("Orango");
}
+void Map48::orangoAnswer(const Common::String &answer) {
+ Common::String properAnswer;
+ for (int i = 0; i < 15 && _data[ANSWER_OFFSET + i]; ++i)
+ properAnswer += (_data[ANSWER_OFFSET + i] & 0x7f) + 29;
+
+ if (answer.equalsIgnoreCase(properAnswer)) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[13] |= CHARFLAG13_ALAMAR;
+ }
+
+ g_maps->_mapPos = Common::Point(8, 5);
+ g_maps->changeMap(0x604, 1);
+ send(SoundMessage(STRING["maps.map48.orango3"]));
+
+ } else {
+ g_maps->_mapPos.x++;
+ updateGame();
+ send(SoundMessage(13, 2, STRING["maps.map48.orango2"]));
+ }
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map48.h b/engines/mm/mm1/maps/map48.h
index c36a038bef6..268c3668ed6 100644
--- a/engines/mm/mm1/maps/map48.h
+++ b/engines/mm/mm1/maps/map48.h
@@ -37,6 +37,11 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Handles Orango answer
+ */
+ void orangoAnswer(const Common::String &answer);
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map49.cpp b/engines/mm/mm1/maps/map49.cpp
index 7797ecbd089..c68eb430cca 100644
--- a/engines/mm/mm1/maps/map49.cpp
+++ b/engines/mm/mm1/maps/map49.cpp
@@ -82,14 +82,17 @@ void Map49::special03() {
void Map49::special04() {
if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
- g_maps->_mapPos = Common::Point(
- _data[MAP_SURFACE_X], _data[MAP_SURFACE_Y]);
- g_maps->changeMap(
- READ_LE_UINT16(&_data[MAP_SURFACE_ID]),
- _data[MAP_SURFACE_SECTION]
- );
-
- send(SoundMessage(STRING["maps.map49.guards2"]));
+ send(SoundMessage(
+ STRING["maps.map49.guards2"],
+ [](const Common::KeyState &) {
+ Map49 &map = *static_cast<Map49 *>(g_maps->_currentMap);
+ g_maps->_mapPos = Common::Point(
+ map[MAP_SURFACE_X], map[MAP_SURFACE_Y]);
+ g_maps->changeMap(
+ READ_LE_UINT16(&map[MAP_SURFACE_ID]),
+ map[MAP_SURFACE_SECTION]);
+ }
+ ));
}
}
@@ -127,7 +130,8 @@ void Map49::special07() {
}
void Map49::special08() {
- if (!g_globals->_activeSpells._s.fire)
+ // WORKAROUND: Fixed acid trap to check for acid protection
+ if (!g_globals->_activeSpells._s.acid)
reduceHP();
reduceHP();
@@ -135,7 +139,8 @@ void Map49::special08() {
}
void Map49::special09() {
- if (!g_globals->_activeSpells._s.acid)
+ // WORKAROUND: Fixed explosion trap to check for fire protection
+ if (!g_globals->_activeSpells._s.fire)
reduceHP();
reduceHP();
diff --git a/engines/mm/mm1/maps/map51.cpp b/engines/mm/mm1/maps/map51.cpp
index 8a020f91bd3..1d9f2c2dd90 100644
--- a/engines/mm/mm1/maps/map51.cpp
+++ b/engines/mm/mm1/maps/map51.cpp
@@ -50,7 +50,7 @@ void Map51::special() {
}
void Map51::special00() {
- send(SoundMessage(STRING["maps.map51.painted"]));
+ send(SoundMessage(STRING["maps.wall_painted"]));
}
void Map51::special01() {
@@ -129,7 +129,7 @@ void Map51::special17() {
}
void Map51::special18() {
- // No implementation
+ special19();
}
void Map51::special19() {
diff --git a/engines/mm/mm1/maps/map53.cpp b/engines/mm/mm1/maps/map53.cpp
index aa6d5a2eab2..45a0a948fb1 100644
--- a/engines/mm/mm1/maps/map53.cpp
+++ b/engines/mm/mm1/maps/map53.cpp
@@ -67,7 +67,7 @@ void Map53::special03() {
visitedExit();
send(SoundMessage(
- STRING["maps.map53.ladder_up"],
+ STRING["maps.map53.ladder"],
[]() {
g_maps->changeMap(0xf01, 3);
}
diff --git a/engines/mm/mm1/maps/map54.cpp b/engines/mm/mm1/maps/map54.cpp
index 764af642b79..cac146f0879 100644
--- a/engines/mm/mm1/maps/map54.cpp
+++ b/engines/mm/mm1/maps/map54.cpp
@@ -59,7 +59,7 @@ void Map54::special00() {
send(SoundMessage(
0, 1, STRING["maps.map54.slot1"],
- 0, 1, STRING["maps.map54.slot2"]
+ 0, 2, STRING["maps.map54.slot2"]
));
return;
}
@@ -74,7 +74,7 @@ void Map54::special00() {
send(SoundMessage(
0, 1, STRING["maps.map54.slot1"],
- 0, 1, STRING["maps.map54.slot3"]
+ 0, 2, STRING["maps.map54.slot3"]
));
return;
}
@@ -120,7 +120,7 @@ void Map54::projector(int index) {
g_globals->_party[i]._flags[13] |= FLAGS[index];
}
- changeMap();
+ sorpigalInn();
Common::String line = Common::String::format(
STRING["maps.map54.projector"].c_str(),
@@ -154,7 +154,7 @@ bool Map54::isWorthy(uint32 &perfTotal) {
return perfTotal >= 65536;
}
-void Map54::changeMap() {
+void Map54::sorpigalInn() {
g_maps->_mapPos = Common::Point(8, 5);
g_maps->changeMap(0x604, 1);
}
diff --git a/engines/mm/mm1/maps/map54.h b/engines/mm/mm1/maps/map54.h
index 05a3195af80..b92faaaf87d 100644
--- a/engines/mm/mm1/maps/map54.h
+++ b/engines/mm/mm1/maps/map54.h
@@ -67,7 +67,7 @@ public:
/**
* Changes the map
*/
- void changeMap();
+ void sorpigalInn();
};
} // namespace Maps
diff --git a/engines/mm/mm1/views/maps/alamar.cpp b/engines/mm/mm1/views/maps/alamar.cpp
index 12ee022c7c9..0cbdb89fa20 100644
--- a/engines/mm/mm1/views/maps/alamar.cpp
+++ b/engines/mm/mm1/views/maps/alamar.cpp
@@ -57,19 +57,16 @@ bool Alamar::msgFocus(const FocusMessage &msg) {
void Alamar::draw() {
MM1::Maps::Map49 &map = *static_cast<MM1::Maps::Map49 *>(g_maps->_currentMap);
+ clearSurface();
if (_succeeded) {
- clearSurface();
writeString(0, 0, STRING["maps.map49.alamar1"]);
writeString(STRING["maps.map49.alamar3"]);
} else if (map[HAS_EYE]) {
- close();
- map.redrawGame();
- send("View", DrawGraphicMessage(7));
- send("View", DrawGraphicMessage(6));
+ send("View", DrawGraphicMessage(65 + 7));
+ send("View", DrawGraphicMessage(65 + 8));
- clearSurface();
writeString(0, 0, STRING["maps.map49.alamar1"]);
writeString(STRING["maps.map49.alamar4"]);
@@ -77,7 +74,6 @@ void Alamar::draw() {
Sound::sound(SOUND_2);
} else {
- clearSurface();
writeString(0, 0, STRING["maps.map49.alamar1"]);
writeString(STRING["maps.map49.alamar2"]);
}
@@ -85,10 +81,16 @@ void Alamar::draw() {
bool Alamar::msgKeypress(const KeypressMessage &msg) {
MM1::Maps::Map49 &map = *static_cast<MM1::Maps::Map49 *>(g_maps->_currentMap);
-
close();
- g_maps->_mapPos.x = 8;
- map.redrawGame();
+
+ if (map[HAS_EYE]) {
+ map[VAL1]++;
+ map.updateGame();
+
+ } else {
+ g_maps->_mapPos.x = 8;
+ map.updateGame();
+ }
return true;
}
diff --git a/engines/mm/mm1/views/maps/dog_statue.cpp b/engines/mm/mm1/views/maps/dog_statue.cpp
index b6d0af9ad49..db87f6179ba 100644
--- a/engines/mm/mm1/views/maps/dog_statue.cpp
+++ b/engines/mm/mm1/views/maps/dog_statue.cpp
@@ -65,14 +65,13 @@ void DogStatue::draw() {
}
bool DogStatue::msgKeypress(const KeypressMessage &msg) {
- if (msg.keycode == Common::KEYCODE_y || msg.keycode == Common::KEYCODE_n) {
+ if (msg.keycode == Common::KEYCODE_y || msg.keycode == Common::KEYCODE_n ||
+ msg.keycode == Common::KEYCODE_ESCAPE) {
MM1::Maps::Map42 &map = *static_cast<MM1::Maps::Map42 *>(g_maps->_currentMap);
close();
if (msg.keycode == Common::KEYCODE_y) {
map.dogDesecrate();
- } else {
- close();
}
}
diff --git a/engines/mm/mm1/views/maps/keeper.cpp b/engines/mm/mm1/views/maps/keeper.cpp
index 3998e5fdfb1..64207df5bf5 100644
--- a/engines/mm/mm1/views/maps/keeper.cpp
+++ b/engines/mm/mm1/views/maps/keeper.cpp
@@ -60,8 +60,7 @@ void Keeper::draw() {
writeString(10, 0, STRING["maps.map54.keeper2"]);
writeString(0, 2, Common::String::format(
STRING["maps.map54.keeper3"].c_str(), perfTotal));
- _textPos.y++;
- writeString(STRING[isWorthy ? "maps.map54.keeper5" :
+ writeString(0, 3, STRING[isWorthy ? "maps.map54.keeper5" :
"maps.map54.keeper4"]);
break;
@@ -75,7 +74,9 @@ bool Keeper::msgKeypress(const KeypressMessage &msg) {
if (++_pageNum == 2) {
close();
- map.changeMap();
+ map.sorpigalInn();
+ } else {
+ redraw();
}
return true;
diff --git a/engines/mm/mm1/views/maps/orango.cpp b/engines/mm/mm1/views/maps/orango.cpp
index 1d5c4852a90..6f1cd35fb84 100644
--- a/engines/mm/mm1/views/maps/orango.cpp
+++ b/engines/mm/mm1/views/maps/orango.cpp
@@ -29,10 +29,8 @@ namespace MM1 {
namespace Views {
namespace Maps {
-#define ANSWER_OFFSET 274
-
Orango::Orango() :
- AnswerEntry("Orango", Common::Point(9, 6), 15) {
+ AnswerEntry("Orango", Common::Point(9, 7), 15) {
_bounds = getLineBounds(17, 24);
}
@@ -43,28 +41,9 @@ void Orango::draw() {
}
void Orango::answerEntered() {
- MM1::Maps::Map &map = *g_maps->_currentMap;
- Common::String properAnswer;
+ MM1::Maps::Map48 &map = *static_cast<MM1::Maps::Map48 *>(g_maps->_currentMap);
close();
-
- for (int i = 0; i < 15 && map[ANSWER_OFFSET + i]; ++i)
- properAnswer += (map[ANSWER_OFFSET + i] & 0x7f) + 29;
-
- if (_answer.equalsIgnoreCase(properAnswer)) {
- for (uint i = 0; i < g_globals->_party.size(); ++i) {
- Character &c = g_globals->_party[i];
- c._flags[13] |= CHARFLAG13_ALAMAR;
- }
-
- g_maps->_mapPos = Common::Point(8, 5);
- g_maps->changeMap(0x604, 1);
- g_events->send(SoundMessage(STRING["maps.map48.orango3"]));
-
- } else {
- g_maps->_mapPos.x++;
- map.updateGame();
- g_events->send(SoundMessage(13, 2, STRING["maps.map48.orango2"]));
- }
+ map.orangoAnswer(_answer);
}
} // namespace Maps
Commit: c1afda0570edc096818652e605dc7b5b0e699ff5
https://github.com/scummvm/scummvm/commit/c1afda0570edc096818652e605dc7b5b0e699ff5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Desert maps will only be mappable if party has map
Changed paths:
engines/mm/mm1/maps/map.h
engines/mm/mm1/maps/map37.h
engines/mm/mm1/maps/map_desert.cpp
engines/mm/mm1/maps/map_desert.h
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 6f574e24ed5..81965c62a2c 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -101,7 +101,6 @@ protected:
uint _mapIndex;
byte _defaultSection;
Common::Array<byte> _data;
- bool _mappingAllowed = true;
private:
/**
* Loads the map's maze data
@@ -150,6 +149,15 @@ public:
*/
virtual void special() = 0;
+ /**
+ * Returns true if mapping is allowed in enhanced mode.
+ * This is to prevent places like the desert where the
+ * players shouldn't be able to see where they are
+ */
+ virtual bool mappingAllowed() const {
+ return true;
+ }
+
/**
* Gets the map name
*/
@@ -167,15 +175,6 @@ public:
return _defaultSection;
}
- /**
- * Returns true if mapping is allowed in enhanced mode.
- * This is to prevent places like the desert where the
- * players shouldn't be able to see where they are
- */
- bool mappingAllowed() const {
- return _mappingAllowed;
- }
-
/**
* Accesses the map data
*/
diff --git a/engines/mm/mm1/maps/map37.h b/engines/mm/mm1/maps/map37.h
index c768696aea6..105c40622fb 100644
--- a/engines/mm/mm1/maps/map37.h
+++ b/engines/mm/mm1/maps/map37.h
@@ -73,14 +73,19 @@ private:
&Map37::special19
};
public:
- Map37() : Map(37, "qvl1", 0xf03, 3) {
- _mappingAllowed = false;
- }
+ Map37() : Map(37, "qvl1", 0xf03, 3) {}
/**
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * This map has some random spinners, so we want to
+ * disable mapping in enhanced mode to avoid spoiling
+ * the surprise
+ */
+ bool mappingAllowed() const override { return false; }
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map_desert.cpp b/engines/mm/mm1/maps/map_desert.cpp
index 96f6131a163..f91c69a14cd 100644
--- a/engines/mm/mm1/maps/map_desert.cpp
+++ b/engines/mm/mm1/maps/map_desert.cpp
@@ -116,6 +116,10 @@ void MapDesert::lost() {
}
}
+bool MapDesert::mappingAllowed() const {
+ return g_globals->_party.hasItem(MAP_OF_DESERT_ID);
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map_desert.h b/engines/mm/mm1/maps/map_desert.h
index e157c05fcdf..7c9e295b451 100644
--- a/engines/mm/mm1/maps/map_desert.h
+++ b/engines/mm/mm1/maps/map_desert.h
@@ -55,6 +55,12 @@ public:
byte defaultSection, int deadCountOffset, RandomMode rndMode) :
Map(index, name, id, defaultSection),
_deadCountOffset(deadCountOffset), _randomMode(rndMode) {}
+
+ /**
+ * Allow mapping of the desert maps in the enhanced version
+ * if the party has the desert map item
+ */
+ bool mappingAllowed() const override;
};
} // namespace Maps
Commit: dbcf3e573c4e7e0c2c4a8c8090e03ac7138bdfbc
https://github.com/scummvm/scummvm/commit/dbcf3e573c4e7e0c2c4a8c8090e03ac7138bdfbc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Renamings for monster level
Changed paths:
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/game/spells_monsters.cpp
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 75f0cabd668..88048289255 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -79,7 +79,7 @@ struct Monster {
byte _field1f;
// Runtime combat fields
- byte _combat1 = 0;
+ byte _level = 0;
bool _checked = false;
byte _status = 0;
byte _hp = 0;
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index fea3e0eb485..b303ffcd7e8 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -1450,7 +1450,7 @@ void Combat::monsterAttackInner() {
_destAC = c._ac._base;
int monsterIndex = getMonsterIndex();
- _attackerLevel = _monsterList[monsterIndex]._combat1 * 2 + 4;
+ _attackerLevel = _monsterList[monsterIndex]._level * 2 + 4;
if (c._condition & (ASLEEP | BLINDED | PARALYZED))
_attackerLevel += 5;
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index eb02f427eb6..35fcd59e3b0 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -40,8 +40,8 @@ void Encounter::execute() {
_bribeFleeCtr = _bribeAlignmentCtr = 0;
_alignmentsChanged = 0;
- byte combat1[MAX_COMBAT_MONSTERS];
- Common::fill(&combat1[0], &combat1[MAX_COMBAT_MONSTERS], 0);
+ byte monsterLevel[MAX_COMBAT_MONSTERS];
+ Common::fill(&monsterLevel[0], &monsterLevel[MAX_COMBAT_MONSTERS], 0);
if (!_flag) {
_monsterList.clear();
@@ -83,7 +83,7 @@ void Encounter::execute() {
}
assert(_monsterCount < MAX_COMBAT_MONSTERS);
- combat1[_monsterCount] = comp;
+ monsterLevel[_monsterCount] = comp;
_monsterNum16 = comp;
_levelIndex += comp;
@@ -100,8 +100,8 @@ void Encounter::execute() {
for (int i = 0; i < maxVal; ++i) {
assert(_monsterCount > 0);
- combat1[_monsterCount] = combat1[_monsterCount - 1];
- _levelIndex += combat1[_monsterCount];
+ monsterLevel[_monsterCount] = monsterLevel[_monsterCount - 1];
+ _levelIndex += monsterLevel[_monsterCount];
_monsIndexes[_monsterCount] = _monsIndexes[_monsterCount - 1];
if (++_monsterCount >= MAX_COMBAT_MONSTERS)
@@ -119,18 +119,18 @@ exit_loop:
_monsterList.clear();
for (int i = 0; i < _monsterCount; ++i) {
- maxVal = (combat1[i] - 1) * 16 + _monsIndexes[i];
- if (combat1[i] < 1 || combat1[i] > 12 || maxVal >= 196) {
- combat1[i] = 10;
+ maxVal = (monsterLevel[i] - 1) * 16 + _monsIndexes[i];
+ if (monsterLevel[i] < 1 || monsterLevel[i] > 12 || maxVal >= 196) {
+ monsterLevel[i] = 10;
_monsIndexes[i] = getRandomNumber(MAX_COMBAT_MONSTERS);
}
// Add monster details to list
- _monsterNum16 = combat1[i];
+ _monsterNum16 = monsterLevel[i];
const Monster &srcMons = g_globals->_monsters[_monsIndexes[i]];
_monsterList.push_back(srcMons);
Monster &mons = _monsterList.back();
- mons._combat1 = combat1[i];
+ mons._level = monsterLevel[i];
if (_monsterNum16 > _val9) {
_val9 = _monsterNum16;
@@ -177,10 +177,10 @@ void Encounter::clearMonsters() {
_monsterList.size();
}
-void Encounter::addMonster(byte id, byte arr1) {
+void Encounter::addMonster(byte id, byte level) {
const Monster &mons = g_globals->_monsters[id];
_monsterList.push_back(mons);
- _monsterList.back()._combat1 = arr1;
+ _monsterList.back()._level = level;
}
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 12ee8727a26..043a66b9413 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -81,7 +81,7 @@ public:
/**
* Adds a monster to the monster list
*/
- void addMonster(byte id, byte arr1);
+ void addMonster(byte id, byte level);
};
} // namespace Game
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index ca92c90f20d..74b67d22b57 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -103,7 +103,7 @@ void SpellsMonsters::spell03_fire() {
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
- int count = _monsterList[getMonsterIndex()]._combat1;
+ int count = _monsterList[getMonsterIndex()]._level;
g_globals->_spellsState._newCondition += count * 6;
damageRandomChar();
@@ -157,7 +157,7 @@ void SpellsMonsters::spell08_paralyze() {
g_globals->_spellsState._resistanceType = RESISTANCE_FEAR;
g_globals->_spellsState._newCondition = PARALYZED;
- if (_monsterList[getMonsterIndex()]._combat1 >= 5) {
+ if (_monsterList[getMonsterIndex()]._level >= 5) {
handlePartyEffects();
} else {
chooseCharacter();
@@ -200,8 +200,8 @@ void SpellsMonsters::spell12_explode() {
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
g_globals->_spellsState._newCondition = getRandomNumber(
- _monsterList[getMonsterIndex()]._combat1);
- _monsterList[getMonsterIndex()]._combat1 = 0;
+ _monsterList[getMonsterIndex()]._level);
+ _monsterList[getMonsterIndex()]._level = 0;
_monsterList[getMonsterIndex()]._status = MONFLAG_DEAD;
removeMonster();
@@ -218,7 +218,7 @@ void SpellsMonsters::spell13_fireball() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 6 *
- _monsterList[getMonsterIndex()]._combat1;
+ _monsterList[getMonsterIndex()]._level;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition) + 4;
add(':');
@@ -235,7 +235,7 @@ void SpellsMonsters::spell14_fireBreath() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 8 *
- _monsterList[getMonsterIndex()]._combat1;
+ _monsterList[getMonsterIndex()]._level;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition);
add(':');
Commit: cf77d251f561a411fea6258bcba0c242ab4eb13f
https://github.com/scummvm/scummvm/commit/cf77d251f561a411fea6258bcba0c242ab4eb13f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Console encounter cmd now accepts monster num
Changed paths:
engines/mm/mm1/console.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 42cd2d33966..26257e247d0 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -326,15 +326,36 @@ bool Console::cmdCast(int argc, const char **argv) {
}
bool Console::cmdEncounter(int argc, const char **argv) {
- if (argc > 1) {
- int encType = strToInt(argv[1]);
- if (encType == -1 || encType == 0 || encType == 1)
- g_globals->_encounters._encounterType =
- (Game::EncounterType)encType;
- }
+ if (argc < 2) {
+ debugPrintf("encounter <monster-num> [<encounter type>]\n");
+ return true;
- g_globals->_encounters.execute();
- return false;
+ } else {
+ Game::Encounter &enc = g_globals->_encounters;
+ int monsterNum = strToInt(argv[1]);
+ if (monsterNum < 1 || monsterNum > MONSTERS_COUNT) {
+ debugPrintf("monster-num must be between 1 and %d\n", MONSTERS_COUNT);
+ return true;
+ }
+
+ int encType = (argc > 2) ? strToInt(argv[2]) :
+ Game::NORMAL_ENCOUNTER;
+ if (encType != -1 || encType == 0 || encType == 1)
+ enc._encounterType = (Game::EncounterType)encType;
+
+ enc.clearMonsters();
+ enc.addMonster(monsterNum, 1);
+
+ enc._flag = true;
+ enc._levelIndex = 80;
+
+ bool monstersOn = g_globals->_encountersOn;
+ g_globals->_encountersOn = true;
+ enc.execute();
+ g_globals->_encountersOn = monstersOn;
+
+ return false;
+ }
}
bool Console::cmdEncounters(int argc, const char **argv) {
Commit: 0178c1b9b33434721fd00027337e0d2a54d90368
https://github.com/scummvm/scummvm/commit/0178c1b9b33434721fd00027337e0d2a54d90368
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Fix drawing monster graphic at start of encounters
Changed paths:
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/text_view.cpp
engines/mm/mm1/views/text_view.h
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 6fdabdad96e..e71394e2888 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -122,7 +122,7 @@ void Encounter::draw() {
if (_mode != ALERT) {
// Display the monster
- msgDrawGraphic(DrawGraphicMessage(enc._monsterImgNum));
+ drawGraphic(enc._monsterImgNum);
// Write the monster list
for (uint i = 0; i < enc._monsterList.size(); ++i) {
diff --git a/engines/mm/mm1/views/text_view.cpp b/engines/mm/mm1/views/text_view.cpp
index cef8c1b19b6..ceccaf7c2d1 100644
--- a/engines/mm/mm1/views/text_view.cpp
+++ b/engines/mm/mm1/views/text_view.cpp
@@ -147,11 +147,14 @@ bool TextView::msgDrawGraphic(const DrawGraphicMessage &msg) {
draw();
// Draw the new image
+ drawGraphic(msg._gfxNum);
+ return true;
+}
+
+void TextView::drawGraphic(int gfxNum) {
const Graphics::ManagedSurface img =
- g_globals->_monsters.getMonsterImage(msg._gfxNum);
+ g_globals->_monsters.getMonsterImage(gfxNum);
getSurface().blitFrom(img, Common::Point(64, 16));
-
- return true;
}
} // namespace Views
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 4a7df7893eb..2fa46d93d75 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -97,6 +97,8 @@ protected:
*/
virtual void timeout();
+ void drawGraphic(int gfxNum);
+
public:
TextView(const Common::String &name);
TextView(const Common::String &name, UIElement *owner);
Commit: 6e88147ca50c1f00b9c8e1114dd37874515abb87
https://github.com/scummvm/scummvm/commit/6e88147ca50c1f00b9c8e1114dd37874515abb87
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Fix clearing commands area at start of encounters
Changed paths:
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index e71394e2888..a4efc7f34c4 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -39,10 +39,11 @@ bool Encounter::msgFocus(const FocusMessage &msg) {
void Encounter::draw() {
Game::Encounter &enc = g_globals->_encounters;
-
- // Clear the commands area
Graphics::ManagedSurface s = getSurface();
- s.fillRect(Common::Rect(31 * 8, 0, 320, 17 * 8), 0);
+
+ if (_mode != ALERT)
+ // Clear the commands area
+ s.fillRect(Common::Rect(241, 0, 320, 128), 0);
switch (_mode) {
case ALERT:
Commit: 507a8133426b756bdb5fb87305d87dc3a39c9f4d
https://github.com/scummvm/scummvm/commit/507a8133426b756bdb5fb87305d87dc3a39c9f4d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Fix script-based encounters setup
Changed paths:
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 35fcd59e3b0..f5df09dd583 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -40,11 +40,8 @@ void Encounter::execute() {
_bribeFleeCtr = _bribeAlignmentCtr = 0;
_alignmentsChanged = 0;
- byte monsterLevel[MAX_COMBAT_MONSTERS];
- Common::fill(&monsterLevel[0], &monsterLevel[MAX_COMBAT_MONSTERS], 0);
-
if (!_flag) {
- _monsterList.clear();
+ _monsterSummaries.clear();
_levelIndex = 0;
}
@@ -82,32 +79,29 @@ void Encounter::execute() {
comp = MIN(maxVal, 10);
}
- assert(_monsterCount < MAX_COMBAT_MONSTERS);
- monsterLevel[_monsterCount] = comp;
- _monsterNum16 = comp;
- _levelIndex += comp;
-
+ assert(_monsterSummaries.size() < MAX_COMBAT_MONSTERS);
_monsterNum = getRandomNumber(16);
- _monsIndexes[_monsterCount] = _monsterNum;
- _monsterCount = (_monsterCount + 1) & 0xff;
+ _monsterSummaries.push_back(MonsterSummary(_monsterNum, comp));
- if (_monsterCount < MAX_COMBAT_MONSTERS) {
- if (_monsterCount >= map[Maps::MAP_MAX_MONSTERS])
+ _monsterLevel = comp;
+ _levelIndex += comp;
+
+ if (_monsterSummaries.size() < MAX_COMBAT_MONSTERS) {
+ if (_monsterSummaries.size() >= map[Maps::MAP_MAX_MONSTERS])
goto exit_loop;
monsterP = getMonster();
maxVal = getRandomNumber(monsterP->_count);
for (int i = 0; i < maxVal; ++i) {
- assert(_monsterCount > 0);
- monsterLevel[_monsterCount] = monsterLevel[_monsterCount - 1];
- _levelIndex += monsterLevel[_monsterCount];
- _monsIndexes[_monsterCount] = _monsIndexes[_monsterCount - 1];
+ assert(!_monsterSummaries.empty());
+ _monsterSummaries.push_back(_monsterSummaries.back());
+ _levelIndex += _monsterSummaries.back()._level;
- if (++_monsterCount >= MAX_COMBAT_MONSTERS)
+ if (_monsterSummaries.size() >= MAX_COMBAT_MONSTERS)
goto exit_loop;
- if (_monsterCount >= map[Maps::MAP_MAX_MONSTERS])
+ if (_monsterSummaries.size() >= map[Maps::MAP_MAX_MONSTERS])
goto exit_loop;
}
} else {
@@ -118,22 +112,25 @@ void Encounter::execute() {
exit_loop:
_monsterList.clear();
- for (int i = 0; i < _monsterCount; ++i) {
- maxVal = (monsterLevel[i] - 1) * 16 + _monsIndexes[i];
- if (monsterLevel[i] < 1 || monsterLevel[i] > 12 || maxVal >= 196) {
- monsterLevel[i] = 10;
- _monsIndexes[i] = getRandomNumber(MAX_COMBAT_MONSTERS);
+ for (uint i = 0; i < _monsterSummaries.size(); ++i) {
+ maxVal = (_monsterSummaries[i]._level - 1) * 16 +
+ _monsterSummaries[i]._num;
+
+ if (_monsterSummaries[i]._level < 1 || _monsterSummaries[i]._level > 12
+ || maxVal >= 196) {
+ _monsterSummaries[i]._level = 10;
+ _monsterSummaries[i]._num = getRandomNumber(MAX_COMBAT_MONSTERS);
}
// Add monster details to list
- _monsterNum16 = monsterLevel[i];
- const Monster &srcMons = g_globals->_monsters[_monsIndexes[i]];
+ _monsterLevel = _monsterSummaries[i]._level;
+ const Monster &srcMons = g_globals->_monsters[_monsterSummaries[i]._num];
_monsterList.push_back(srcMons);
Monster &mons = _monsterList.back();
- mons._level = monsterLevel[i];
+ mons._level = _monsterSummaries[i]._level;
- if (_monsterNum16 > _val9) {
- _val9 = _monsterNum16;
+ if (_monsterLevel > _val9) {
+ _val9 = _monsterLevel;
_fleeThreshold = mons._field10;
_monsterImgNum = mons._field1f;
}
@@ -158,8 +155,8 @@ void Encounter::randomAdjust() {
}
const Monster *Encounter::getMonster() {
- assert(_monsterNum > 0 && _monsterNum16 > 0);
- return &g_globals->_monsters[_monsterNum + ((_monsterNum16 - 1) * 16)];
+ assert(_monsterNum > 0 && _monsterLevel > 0);
+ return &g_globals->_monsters[_monsterNum + ((_monsterLevel - 1) * 16)];
}
bool Encounter::checkSurroundParty() const {
@@ -174,13 +171,11 @@ void Encounter::changeCharAlignment(Alignment align) {
}
void Encounter::clearMonsters() {
- _monsterList.size();
+ _monsterSummaries.clear();
}
void Encounter::addMonster(byte id, byte level) {
- const Monster &mons = g_globals->_monsters[id];
- _monsterList.push_back(mons);
- _monsterList.back()._level = level;
+ _monsterSummaries.push_back(MonsterSummary(id, level));
}
} // namespace Game
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 043a66b9413..95eb1246530 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -41,10 +41,16 @@ class Encounter : public GameLogic {
private:
int _levelOffset = 0;
int _val9 = 0;
- int _monsterNum16 = 0;
+ int _monsterLevel = 0;
int _totalLevels = 0;
int _monsterNum = 0;
- byte _monsIndexes[MAX_COMBAT_MONSTERS];
+ struct MonsterSummary {
+ byte _num;
+ byte _level;
+ MonsterSummary() : _num(0), _level(0) {}
+ MonsterSummary(byte num, byte level) : _num(num), _level(level) {}
+ };
+ Common::Array<MonsterSummary> _monsterSummaries;
void randomAdjust();
const Monster *getMonster();
@@ -53,7 +59,6 @@ public:
int _bribeAlignmentCtr = 0, _bribeFleeCtr = 0;
int _alignmentsChanged = 0;
int _monsterImgNum = 0;
- int _monsterCount = 0; // == _monsterList.size()
int _highestLevel = 0;
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
Commit: 0ae511346e20b8459e44fefd9b8ab7179be6f40f
https://github.com/scummvm/scummvm/commit/0ae511346e20b8459e44fefd9b8ab7179be6f40f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Rename some monster fields
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/encounter.cpp
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 0cd594ca92c..82919bcf996 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -41,7 +41,7 @@ bool Monsters::load() {
line = Common::String(line.c_str() + 17);
mon._count = getNextValue(line);
- mon._field10 = getNextValue(line);
+ mon._fleeThreshold = getNextValue(line);
mon._defaultHP = getNextValue(line);
mon._defaultAC = getNextValue(line);
mon._maxDamage = getNextValue(line);
@@ -53,9 +53,9 @@ bool Monsters::load() {
mon._field1a = getNextValue(line);
mon._bonusOnTouch = getNextValue(line);
mon._specialAbility = getNextValue(line);
- mon._field1d = getNextValue(line);
+ mon._specialThreshold = getNextValue(line);
mon._field1e = getNextValue(line);
- mon._field1f = getNextValue(line);
+ mon._imgNum = getNextValue(line);
}
return true;
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 88048289255..8335bbd7eaf 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -62,7 +62,7 @@ enum Field1E {
struct Monster {
Common::String _name; // char _name[15];
byte _count;
- byte _field10;
+ byte _fleeThreshold;
byte _defaultHP;
byte _defaultAC;
byte _maxDamage;
@@ -70,13 +70,13 @@ struct Monster {
byte _speed;
uint16 _experience;
byte _field18;
- byte _resistUndead; // MonsterResistUndead
+ byte _resistUndead;
byte _field1a;
byte _bonusOnTouch;
byte _specialAbility;
- byte _field1d;
+ byte _specialThreshold;
byte _field1e;
- byte _field1f;
+ byte _imgNum;
// Runtime combat fields
byte _level = 0;
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b303ffcd7e8..b66c872e8a7 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -625,7 +625,7 @@ bool Combat::checkMonsterSpells() {
}
if (!_monsterP->_specialAbility || (_monsterP->_specialAbility & 0x80) ||
- (getRandomNumber(100) >= _monsterP->_field1d) ||
+ (getRandomNumber(100) >= _monsterP->_specialThreshold) ||
!(_monsterP->_field1e & 0xf))
return false;
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index f5df09dd583..1355f1f952e 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -131,8 +131,8 @@ exit_loop:
if (_monsterLevel > _val9) {
_val9 = _monsterLevel;
- _fleeThreshold = mons._field10;
- _monsterImgNum = mons._field1f;
+ _fleeThreshold = mons._fleeThreshold;
+ _monsterImgNum = mons._imgNum;
}
}
Commit: a3a9a280a4ba495161993c576e3e9cf32c8568f9
https://github.com/scummvm/scummvm/commit/a3a9a280a4ba495161993c576e3e9cf32c8568f9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:48+01:00
Commit Message:
MM: MM1: Rename encounter flag for better clarity
Changed paths:
engines/mm/mm1/console.cpp
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/maps/map.cpp
engines/mm/mm1/maps/map01.cpp
engines/mm/mm1/maps/map03.cpp
engines/mm/mm1/maps/map05.cpp
engines/mm/mm1/maps/map07.cpp
engines/mm/mm1/maps/map10.cpp
engines/mm/mm1/maps/map11.cpp
engines/mm/mm1/maps/map13.cpp
engines/mm/mm1/maps/map14.cpp
engines/mm/mm1/maps/map15.cpp
engines/mm/mm1/maps/map16.cpp
engines/mm/mm1/maps/map17.cpp
engines/mm/mm1/maps/map19.cpp
engines/mm/mm1/maps/map20.cpp
engines/mm/mm1/maps/map21.cpp
engines/mm/mm1/maps/map22.cpp
engines/mm/mm1/maps/map23.cpp
engines/mm/mm1/maps/map24.cpp
engines/mm/mm1/maps/map25.cpp
engines/mm/mm1/maps/map26.cpp
engines/mm/mm1/maps/map29.cpp
engines/mm/mm1/maps/map30.cpp
engines/mm/mm1/maps/map31.cpp
engines/mm/mm1/maps/map33.cpp
engines/mm/mm1/maps/map37.cpp
engines/mm/mm1/maps/map40.cpp
engines/mm/mm1/maps/map42.cpp
engines/mm/mm1/maps/map43.cpp
engines/mm/mm1/views/maps/arrested.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 26257e247d0..78a16eb91b6 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -346,7 +346,7 @@ bool Console::cmdEncounter(int argc, const char **argv) {
enc.clearMonsters();
enc.addMonster(monsterNum, 1);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
bool monstersOn = g_globals->_encountersOn;
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 1355f1f952e..55175062f06 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -40,7 +40,9 @@ void Encounter::execute() {
_bribeFleeCtr = _bribeAlignmentCtr = 0;
_alignmentsChanged = 0;
- if (!_flag) {
+ // In manual mode, the scripts have already set up
+ // a list of monsters to use
+ if (!_manual) {
_monsterSummaries.clear();
_levelIndex = 0;
}
@@ -59,8 +61,8 @@ void Encounter::execute() {
_totalLevels /= 2;
_highestLevel /= 2;
- bool firstLoop = !_flag;
- _flag = false;
+ bool firstLoop = !_manual;
+ _manual = false;
while (firstLoop || _levelIndex < _totalLevels) {
randomAdjust();
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 95eb1246530..1589aff9897 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -62,7 +62,7 @@ public:
int _highestLevel = 0;
EncounterType _encounterType = NORMAL_SURPRISED;
byte _fleeThreshold = 0;
- bool _flag = false;
+ bool _manual = false;
int _levelIndex = 0;
public:
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index f3120b108ab..1cf2e24a4ff 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -112,7 +112,7 @@ void Map::encounter(const byte *id1, const byte *id2) {
for (int i = 0; i < 14 && *id1; ++i, ++id1, ++id2)
enc.addMonster(*id1, *id2);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 64;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map01.cpp b/engines/mm/mm1/maps/map01.cpp
index 6f5b05e6bc2..ed35bc803dc 100644
--- a/engines/mm/mm1/maps/map01.cpp
+++ b/engines/mm/mm1/maps/map01.cpp
@@ -130,7 +130,7 @@ void Map01::special08() {
for (uint i = 0; i < count; ++i)
enc.addMonster(4, 9);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map03.cpp b/engines/mm/mm1/maps/map03.cpp
index 38a5a9eb651..98418911056 100644
--- a/engines/mm/mm1/maps/map03.cpp
+++ b/engines/mm/mm1/maps/map03.cpp
@@ -194,7 +194,7 @@ void Map03::special15() {
Game::Encounter &enc = g_globals->_encounters;
enc._levelIndex = 80;
- enc._flag = true;
+ enc._manual = true;
enc.clearMonsters();
for (int i = 0; i < monsterCount; ++i)
diff --git a/engines/mm/mm1/maps/map05.cpp b/engines/mm/mm1/maps/map05.cpp
index 8c6b8bc5117..6eaa043aacc 100644
--- a/engines/mm/mm1/maps/map05.cpp
+++ b/engines/mm/mm1/maps/map05.cpp
@@ -88,7 +88,7 @@ void Map05::special05() {
enc.addMonster(14, 1);
enc._levelIndex = 80;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
@@ -179,7 +179,7 @@ void Map05::encounter(int monsterId) {
enc.addMonster(monsterId, 1);
enc._levelIndex = 80;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map07.cpp b/engines/mm/mm1/maps/map07.cpp
index 6c93eff53ea..1dbff601767 100644
--- a/engines/mm/mm1/maps/map07.cpp
+++ b/engines/mm/mm1/maps/map07.cpp
@@ -205,7 +205,7 @@ void Map07::setMonsters(int id1, int id2) {
for (int i = 0; i < 6; ++i)
enc.addMonster(id1, id2);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 48;
}
diff --git a/engines/mm/mm1/maps/map10.cpp b/engines/mm/mm1/maps/map10.cpp
index 4ace9050aea..8a8add50df8 100644
--- a/engines/mm/mm1/maps/map10.cpp
+++ b/engines/mm/mm1/maps/map10.cpp
@@ -171,7 +171,7 @@ void Map10::special30() {
enc.addMonster(9, 9);
enc._levelIndex = 64;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
@@ -189,7 +189,7 @@ void Map10::special32() {
enc.addMonster(8, 12);
enc._levelIndex = 64;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map11.cpp b/engines/mm/mm1/maps/map11.cpp
index 1300c3b4e5a..22b4974ae1d 100644
--- a/engines/mm/mm1/maps/map11.cpp
+++ b/engines/mm/mm1/maps/map11.cpp
@@ -182,7 +182,7 @@ void Map11::challenge() {
enc.addMonster(7, 8);
enc._levelIndex = 96;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map13.cpp b/engines/mm/mm1/maps/map13.cpp
index c0fe0c835ea..8b31510a462 100644
--- a/engines/mm/mm1/maps/map13.cpp
+++ b/engines/mm/mm1/maps/map13.cpp
@@ -69,7 +69,7 @@ void Map13::special() {
enc.addMonster(_data[MONSTER_ID1 + index + i],
_data[MONSTER_ID2 + index + i]);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 48;
enc.execute();
}
@@ -171,7 +171,7 @@ void Map13::encounter(size_t count, byte id1, byte id2) {
for (size_t i = 0; i < count; ++i)
enc.addMonster(id1, id2);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 64;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map14.cpp b/engines/mm/mm1/maps/map14.cpp
index 20da662eb56..96bb57d3122 100644
--- a/engines/mm/mm1/maps/map14.cpp
+++ b/engines/mm/mm1/maps/map14.cpp
@@ -59,7 +59,7 @@ void Map14::special() {
enc.addMonster(id1, 7);
enc._levelIndex = 5;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
@@ -100,7 +100,7 @@ void Map14::special00() {
enc.addMonster(13, 8);
enc._levelIndex = 80;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
}
diff --git a/engines/mm/mm1/maps/map15.cpp b/engines/mm/mm1/maps/map15.cpp
index 6b9fe759305..9ca15fa60df 100644
--- a/engines/mm/mm1/maps/map15.cpp
+++ b/engines/mm/mm1/maps/map15.cpp
@@ -63,7 +63,7 @@ void Map15::special() {
for (uint i = 0; i < _data[VAL1]; ++i)
enc.addMonster(7, 8);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
@@ -90,7 +90,7 @@ void Map15::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, 11);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
@@ -120,7 +120,7 @@ void Map15::special01() {
enc.clearMonsters();
enc.addMonster(15, 9);
enc._levelIndex = 5;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
}
@@ -136,7 +136,7 @@ void Map15::special02() {
enc.addMonster(15, 9);
enc._levelIndex = 48;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
@@ -150,7 +150,7 @@ void Map15::special03() {
enc.addMonster(15, 9);
enc._levelIndex = 48;
- enc._flag = true;
+ enc._manual = true;
}
void Map15::special04() {
diff --git a/engines/mm/mm1/maps/map16.cpp b/engines/mm/mm1/maps/map16.cpp
index 46278d0c4c0..d8fd0b635b6 100644
--- a/engines/mm/mm1/maps/map16.cpp
+++ b/engines/mm/mm1/maps/map16.cpp
@@ -61,7 +61,7 @@ void Map16::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, 11);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
@@ -104,7 +104,7 @@ void Map16::special00() {
enc.addMonster(12, 11);
enc._levelIndex = 80;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
);
diff --git a/engines/mm/mm1/maps/map17.cpp b/engines/mm/mm1/maps/map17.cpp
index 8901c565836..102a6c94ebf 100644
--- a/engines/mm/mm1/maps/map17.cpp
+++ b/engines/mm/mm1/maps/map17.cpp
@@ -60,7 +60,7 @@ void Map17::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, 11);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
diff --git a/engines/mm/mm1/maps/map19.cpp b/engines/mm/mm1/maps/map19.cpp
index 84fcac22356..b2f11b72558 100644
--- a/engines/mm/mm1/maps/map19.cpp
+++ b/engines/mm/mm1/maps/map19.cpp
@@ -120,7 +120,7 @@ void Map19::encounter() {
enc.addMonster(_data[VAL7], _data[VAL6]);
enc.addMonster(_data[VAL5], _data[VAL4]);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map20.cpp b/engines/mm/mm1/maps/map20.cpp
index 8cd67350f1f..ffec1a6adb8 100644
--- a/engines/mm/mm1/maps/map20.cpp
+++ b/engines/mm/mm1/maps/map20.cpp
@@ -63,7 +63,7 @@ void Map20::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, 11);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map21.cpp b/engines/mm/mm1/maps/map21.cpp
index 48efa5983ba..b6aadf2fcd0 100644
--- a/engines/mm/mm1/maps/map21.cpp
+++ b/engines/mm/mm1/maps/map21.cpp
@@ -67,7 +67,7 @@ void Map21::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, 11);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
@@ -94,7 +94,7 @@ void Map21::special00() {
enc._levelIndex = 80;
enc._encounterType = Game::FORCE_SURPRISED;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
);
diff --git a/engines/mm/mm1/maps/map22.cpp b/engines/mm/mm1/maps/map22.cpp
index 3d9e13f51a9..0c0ec3952f3 100644
--- a/engines/mm/mm1/maps/map22.cpp
+++ b/engines/mm/mm1/maps/map22.cpp
@@ -127,7 +127,7 @@ void Map22::special02() {
enc.addMonster(id1, id2);
enc._levelIndex = 32;
- enc._flag = true;
+ enc._manual = true;
enc._encounterType = Game::FORCE_SURPRISED;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map23.cpp b/engines/mm/mm1/maps/map23.cpp
index 4b525d10da2..b22ad0ca9eb 100644
--- a/engines/mm/mm1/maps/map23.cpp
+++ b/engines/mm/mm1/maps/map23.cpp
@@ -137,7 +137,7 @@ void Map23::special09() {
enc.addMonster(2, 4);
enc._levelIndex = 80;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
));
diff --git a/engines/mm/mm1/maps/map24.cpp b/engines/mm/mm1/maps/map24.cpp
index 37b449d61fa..27306775f9a 100644
--- a/engines/mm/mm1/maps/map24.cpp
+++ b/engines/mm/mm1/maps/map24.cpp
@@ -93,7 +93,7 @@ void Map24::special02() {
for (int i = 1; i < monsterCount; ++i)
enc.addMonster(14, 7);
- enc._flag = true;
+ enc._manual = true;
enc._encounterType = Game::FORCE_SURPRISED;
enc._levelIndex = 40;
enc.execute();
@@ -114,7 +114,7 @@ void Map24::special03() {
for (int i = 1; i < monsterCount; ++i)
enc.addMonster(14, 7);
- enc._flag = true;
+ enc._manual = true;
enc._encounterType = Game::FORCE_SURPRISED;
enc._levelIndex = 40;
enc.execute();
diff --git a/engines/mm/mm1/maps/map25.cpp b/engines/mm/mm1/maps/map25.cpp
index fbff4b37643..270cb768cbd 100644
--- a/engines/mm/mm1/maps/map25.cpp
+++ b/engines/mm/mm1/maps/map25.cpp
@@ -57,7 +57,7 @@ void Map25::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(val, 11);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
@@ -80,7 +80,7 @@ void Map25::special() {
enc.addMonster(12, 12);
enc._levelIndex = 64;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
);
@@ -181,7 +181,7 @@ void Map25::nativesAttack() {
g_maps->clearSpecial();
enc._levelIndex = 64;
- enc._flag = true;
+ enc._manual = true;
enc.execute();
}
);
diff --git a/engines/mm/mm1/maps/map26.cpp b/engines/mm/mm1/maps/map26.cpp
index 007c1ac6e51..332a9638cab 100644
--- a/engines/mm/mm1/maps/map26.cpp
+++ b/engines/mm/mm1/maps/map26.cpp
@@ -75,7 +75,7 @@ void Map26::special00() {
enc.addMonster(5, 5);
enc._levelIndex = 80;
- enc._flag = true;
+ enc._manual = true;
enc._encounterType = Game::FORCE_SURPRISED;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map29.cpp b/engines/mm/mm1/maps/map29.cpp
index da6b33f4140..e229ace4dbf 100644
--- a/engines/mm/mm1/maps/map29.cpp
+++ b/engines/mm/mm1/maps/map29.cpp
@@ -59,7 +59,7 @@ void Map29::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, 11);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
@@ -127,7 +127,7 @@ void Map29::special01() {
for (int i = 1; i < 13; ++i)
enc.addMonster(3, 5);
- enc._flag = true;
+ enc._manual = true;
enc._encounterType = Game::FORCE_SURPRISED;
enc._levelIndex = 80;
enc.execute();
@@ -159,7 +159,7 @@ void Map29::special03() {
for (int i = 1; i < monsterCount; ++i)
enc.addMonster(1, 7);
- enc._flag = true;
+ enc._manual = true;
enc._encounterType = Game::FORCE_SURPRISED;
enc._levelIndex = 80;
enc.execute();
diff --git a/engines/mm/mm1/maps/map30.cpp b/engines/mm/mm1/maps/map30.cpp
index 82ef1bb9bb1..008085b2136 100644
--- a/engines/mm/mm1/maps/map30.cpp
+++ b/engines/mm/mm1/maps/map30.cpp
@@ -60,7 +60,7 @@ void Map30::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, id2);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 96;
enc.execute();
return;
diff --git a/engines/mm/mm1/maps/map31.cpp b/engines/mm/mm1/maps/map31.cpp
index 892e8d1265d..37d4c2a37e0 100644
--- a/engines/mm/mm1/maps/map31.cpp
+++ b/engines/mm/mm1/maps/map31.cpp
@@ -106,7 +106,7 @@ void Map31::encounter() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(8, 12);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map33.cpp b/engines/mm/mm1/maps/map33.cpp
index 53d3629af28..6ca136e1529 100644
--- a/engines/mm/mm1/maps/map33.cpp
+++ b/engines/mm/mm1/maps/map33.cpp
@@ -94,7 +94,7 @@ void Map33::special() {
enc.addMonster(MONSTER_IDS21[idx], MONSTER_IDS22[idx]);
}
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
break;
@@ -118,7 +118,7 @@ void Map33::special() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(id1, id2);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 64;
}
@@ -138,7 +138,7 @@ void Map33::special00() {
for (int i = 0; i < 10; ++i)
enc.addMonster(MONSTER_IDS11[i], MONSTER_IDS12[i]);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
@@ -202,7 +202,7 @@ void Map33::search(const Common::String &msg) {
for (int i = 1; i < monsterCount; ++i)
enc.addMonster(10, 7);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map37.cpp b/engines/mm/mm1/maps/map37.cpp
index ad1e6fcb688..c617fb468f9 100644
--- a/engines/mm/mm1/maps/map37.cpp
+++ b/engines/mm/mm1/maps/map37.cpp
@@ -110,7 +110,7 @@ void Map37::special04() {
enc.addMonster(14, 8);
enc.addMonster(16, 12);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map40.cpp b/engines/mm/mm1/maps/map40.cpp
index 2db0c2c8cad..af47a646eb6 100644
--- a/engines/mm/mm1/maps/map40.cpp
+++ b/engines/mm/mm1/maps/map40.cpp
@@ -179,7 +179,7 @@ void Map40::archerResist() {
enc.addMonster(12, 10);
enc.addMonster(15, 12);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 112;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map42.cpp b/engines/mm/mm1/maps/map42.cpp
index 74f261a4b6e..931abafd864 100644
--- a/engines/mm/mm1/maps/map42.cpp
+++ b/engines/mm/mm1/maps/map42.cpp
@@ -76,7 +76,7 @@ void Map42::special02() {
for (int i = 1; i < 13; ++i)
enc.addMonster(8, 5);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 64;
enc.execute();
}
@@ -175,7 +175,7 @@ void Map42::dogDesecrate() {
for (int i = 0; i < (int)count; ++i)
enc.addMonster(4, 10);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 20;
enc.execute();
}
diff --git a/engines/mm/mm1/maps/map43.cpp b/engines/mm/mm1/maps/map43.cpp
index b2e8a85ab28..37c11a05054 100644
--- a/engines/mm/mm1/maps/map43.cpp
+++ b/engines/mm/mm1/maps/map43.cpp
@@ -129,7 +129,7 @@ void Map43::special06() {
for (int i = 0; i < 8; ++i)
enc.addMonster(13, 7);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 80;
enc.execute();
}
diff --git a/engines/mm/mm1/views/maps/arrested.cpp b/engines/mm/mm1/views/maps/arrested.cpp
index 9f4da497a55..bcd4ae5c0fb 100644
--- a/engines/mm/mm1/views/maps/arrested.cpp
+++ b/engines/mm/mm1/views/maps/arrested.cpp
@@ -77,7 +77,7 @@ void Arrested::attack() {
for (int i = 0; i < monsterCount; ++i)
enc.addMonster(6, 10);
- enc._flag = true;
+ enc._manual = true;
enc._levelIndex = 64;
enc._encounterType = Game::FORCE_SURPRISED;
enc.execute();
Commit: 111408353c1316268bdbb12ad38c465c96319895
https://github.com/scummvm/scummvm/commit/111408353c1316268bdbb12ad38c465c96319895
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Fix monster data list
Changed paths:
devtools/create_mm/files/mm1/monsters.txt
engines/mm/mm1/console.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/encounter.cpp
engines/mm/mm1/game/encounter.h
engines/mm/mm1/views/combat.cpp
diff --git a/devtools/create_mm/files/mm1/monsters.txt b/devtools/create_mm/files/mm1/monsters.txt
index c3dbbd092c7..f4765d782fd 100644
--- a/devtools/create_mm/files/mm1/monsters.txt
+++ b/devtools/create_mm/files/mm1/monsters.txt
@@ -1,195 +1,195 @@
-"FLESH EATER ", 6, 0, 2, 2, 6, 1, 7, 50, 0, 0, 0, 0, 130, 0, 0, 16, 4
-"BATTLE RAT ", 10, 1, 1, 3, 3, 1, 12, 50, 0, 2, 0, 0, 130, 0, 0, 0, 6
-"SLITHER BEAST ", 6, 0, 2, 4, 8, 1, 10, 125, 0, 0, 0, 0, 0, 0, 0, 0, 35
-"GNOME ", 6, 50, 3, 5, 6, 1, 12, 125, 0, 2, 20, 1, 0, 132, 0, 6, 8
-"GOBLIN ", 12, 0, 1, 4, 6, 1, 10, 50, 0, 2, 0, 0, 0, 131, 0, 4, 15
-"GREMLIN ", 6, 1, 1, 3, 3, 2, 4, 125, 0, 10, 0, 4, 129, 0, 0, 0, 10
-"GUARDSMAN ", 6, 10, 0, 2, 6, 1, 14, 75, 0, 2, 0, 0, 0, 134, 0, 150, 55
-"KOBOLD ", 10, 1, 1, 4, 4, 1, 6, 50, 0, 2, 0, 0, 0, 131, 0, 4, 5
-"MUTANT LARVA ", 6, 0, 0, 0, 3, 1, 2, 50, 0, 0, 0, 7, 130, 0, 0, 0, 20
-"ORC ", 12, 5, 2, 4, 6, 1, 11, 75, 0, 10, 0, 0, 0, 134, 0, 22, 14
-"POLTERGEIST ", 6, 0, 1, 0, 2, 2, 16, 150, 0, 0, 128, 7, 131, 0, 0, 160, 60
-"RABID JACKAL ", 6, 0, 0, 3, 2, 1, 15, 50, 0, 0, 0, 0, 130, 0, 0, 16, 29
-"SKELETON ", 12, 0, 1, 3, 6, 1, 9, 50, 0, 2, 128, 7, 0, 0, 0, 160, 63
-"SNAKE ", 6, 0, 0, 2, 3, 1, 17, 125, 0, 0, 0, 0, 132, 0, 0, 16, 35
-"SPRITE ", 8, 60, 0, 10, 2, 1, 20, 250, 0, 11, 30, 1, 133, 1, 50, 8, 9
-"VAMPIRE BAT ", 8, 0, 0, 2, 3, 1, 14, 125, 0, 0, 0, 0, 134, 0, 0, 16, 24
-"MINOR DEMON ", 10, 0, 10, 5, 8, 2, 16, 200, 0, 5, 20, 15, 135, 2, 25, 218, 11
-"DEMON DOG ", 10, 3, 8, 3, 10, 2, 14, 100, 0, 0, 0, 0, 0, 0, 0, 16, 32
-"DUNG BEETLE ", 6, 1, 8, 6, 8, 1, 8, 100, 0, 8, 0, 1, 130, 0, 0, 16, 1
-"FIRE ANT ", 15, 0, 5, 5, 6, 1, 7, 100, 0, 26, 0, 67, 0, 3, 10, 20, 0
-"GHOUL ", 6, 0, 8, 4, 5, 3, 13, 200, 0, 5, 128, 7, 136, 0, 0, 16, 58
-"GNOLL ", 10, 0, 8, 5, 8, 1, 10, 100, 0, 10, 0, 0, 0, 134, 0, 6, 15
-"HAG ", 2, 0, 3, 1, 4, 2, 8, 100, 0, 1, 0, 0, 138, 4, 20, 20, 12
-"LOCUST PLAGUE ", 4, 0, 8, 5, 1, 10, 17, 200, 0, 0, 0, 7, 130, 32, 10, 47, 2
-"ORC LEADER ", 1, 0, 10, 5, 8, 1, 14, 100, 0, 28, 0, 0, 0, 138, 0, 38, 14
-"RABID LEPER ", 4, 0, 5, 0, 3, 1, 11, 100, 0, 0, 0, 0, 137, 0, 0, 16, 65
-"ROTTING CORPSE ", 6, 0, 8, 2, 4, 2, 3, 100, 0, 0, 128, 7, 137, 0, 0, 16, 65
-"SAVAGE SHREW ", 4, 5, 4, 3, 5, 3, 13, 150, 0, 0, 0, 0, 0, 0, 0, 0, 32
-"STRANGLING VINE", 10, 0, 1, 3, 3, 4, 6, 100, 0, 40, 0, 3, 134, 0, 0, 51, 47
-"THIEF ", 8, 0, 6, 3, 8, 1, 16, 100, 0, 20, 0, 0, 139, 134, 0, 4, 49
-"TROGLODYTE ", 6, 1, 8, 5, 4, 3, 11, 100, 0, 10, 0, 3, 132, 5, 20, 22, 37
-"ZOMBIE ", 8, 0, 8, 2, 8, 1, 2, 100, 0, 0, 128, 7, 130, 0, 0, 32, 7
-"ACIDIC BLOB ", 6, 0, 8, 1, 8, 2, 8, 44, 1, 0, 0, 127, 140, 6, 20, 118, 20
-"CENTAUR ", 12, 60, 20, 4, 4, 4, 12, 200, 0, 27, 0, 3, 0, 7, 20, 20, 18
-"CLERIC ", 4, 10, 15, 5, 8, 1, 12, 44, 1, 11, 0, 0, 0, 8, 50, 20, 53
-"MINOR DEVIL ", 10, 0, 15, 4, 4, 2, 15, 250, 0, 61, 20, 15, 136, 2, 30, 234, 11
-"FIRE BEETLE ", 5, 0, 16, 7, 15, 1, 6, 200, 0, 2, 0, 65, 0, 3, 30, 22, 1
-"GARGOYLE ", 6, 0, 24, 5, 4, 4, 12, 44, 1, 3, 20, 15, 136, 0, 0, 16, 11
-"GARGANTUAN ANT ", 6, 0, 18, 8, 12, 1, 9, 200, 0, 24, 0, 3, 0, 0, 0, 160, 0
-"DINOLIZARD ", 6, 0, 16, 5, 10, 1, 11, 200, 0, 0, 0, 3, 0, 0, 0, 16, 36
-"GIANT SPIDER ", 6, 1, 20, 5, 8, 1, 18, 200, 0, 1, 0, 1, 140, 0, 0, 16, 0
-"HARPY ", 6, 0, 15, 3, 5, 3, 15, 200, 0, 28, 0, 3, 0, 8, 10, 20, 25
-"HIPPOGRIFF ", 6, 5, 18, 5, 8, 3, 14, 200, 0, 12, 0, 0, 138, 0, 0, 16, 39
-"KILLER BEES ", 4, 0, 10, 10, 2, 10, 16, 44, 1, 0, 0, 7, 132, 32, 20, 42, 2
-"PEGASUS ", 6, 90, 25, 4, 8, 3, 20, 250, 0, 27, 10, 15, 135, 9, 10, 4, 38
-"SHADOW BEAST ", 6, 0, 20, 3, 5, 1, 18, 200, 0, 0, 0, 15, 141, 0, 0, 32, 60
-"WILD BOAR ", 6, 5, 15, 3, 12, 1, 14, 200, 0, 0, 0, 0, 0, 0, 0, 16, 32
-"WOLVERINE ", 3, 0, 10, 5, 5, 3, 12, 250, 0, 10, 0, 1, 0, 0, 0, 16, 29
-"BARBARIAN ", 10, 5, 50, 8, 12, 2, 15, 144, 1, 12, 20, 1, 0, 140, 0, 170, 23
-"CARYATID GUARD ", 6, 2, 20, 5, 10, 1, 15, 144, 1, 1, 25, 255, 142, 9, 10, 54, 64
-"COCKATRICE ", 6, 3, 28, 4, 8, 1, 8, 244, 1, 0, 0, 3, 143, 0, 0, 16, 28
-"CYCLOPS ", 8, 1, 32, 6, 15, 2, 10, 144, 1, 28, 0, 1, 0, 148, 0, 168, 22
-"DRUID ", 4, 2, 24, 4, 8, 2, 14, 144, 1, 3, 0, 1, 138, 7, 50, 22, 53
-"RHINO BEETLE ", 4, 0, 25, 7, 20, 1, 7, 244, 1, 24, 0, 3, 0, 6, 30, 35, 3
-"GIANT CENTIPEDE", 4, 0, 15, 5, 4, 8, 9, 244, 1, 2, 0, 3, 136, 0, 0, 32, 1
-"MAGICIAN ", 3, 1, 25, 5, 8, 1, 15, 88, 2, 29, 0, 1, 0, 10, 90, 24, 52
-"MILITIAMAN ", 6, 10, 30, 9, 10, 2, 9, 44, 1, 2, 0, 1, 0, 138, 0, 150, 50
-"ORC CHIEFTAIN ", 1, 0, 60, 10, 12, 2, 15, 244, 1, 28, 0, 1, 136, 140, 0, 170, 14
-"OGRE ", 6, 0, 45, 7, 10, 2, 12, 94, 1, 12, 0, 1, 0, 140, 0, 170, 19
-"SATYR ", 5, 50, 28, 5, 8, 2, 10, 44, 1, 26, 0, 15, 135, 8, 40, 24, 18
-"SWARMING WASPS ", 4, 0, 20, 4, 2, 10, 17, 144, 1, 0, 0, 7, 132, 32, 25, 47, 2
-"UNICORN ", 4, 90, 35, 8, 10, 3, 22, 244, 1, 7, 20, 127, 141, 9, 20, 69, 38
-"WEREWOLF ", 4, 10, 30, 7, 8, 2, 14, 144, 1, 0, 0, 7, 137, 0, 0, 144, 30
-"WIGHT ", 6, 0, 20, 6, 10, 1, 12, 244, 1, 0, 128, 7, 142, 0, 0, 160, 60
-"BARBARIAN CHIEF", 1, 0, 80, 10, 12, 3, 18, 32, 3, 28, 0, 3, 0, 143, 0, 184, 23
-"BASILISK ", 4, 2, 30, 5, 15, 1, 14, 232, 3, 0, 0, 3, 143, 11, 30, 163, 45
-"CELESTIAL STAG ", 2, 1, 50, 14, 10, 3, 19, 188, 2, 34, 0, 3, 0, 0, 0, 32, 39
-"DUST DEMON ", 3, 0, 30, 9, 12, 3, 15, 88, 2, 1, 0, 15, 7, 7, 20, 154, 34
-"GIANT SCORPION ", 4, 0, 30, 7, 8, 3, 13, 88, 2, 0, 0, 3, 12, 0, 0, 32, 0
-"5 HEADED HYDRA ", 1, 0, 80, 7, 8, 5, 12, 220, 5, 60, 0, 3, 0, 14, 40, 160, 44
-"WARRIOR CAT ", 4, 5, 40, 6, 6, 4, 17, 88, 2, 0, 0, 3, 0, 0, 0, 16, 33
-"MINOTAUR ", 2, 0, 55, 7, 35, 1, 15, 220, 5, 60, 20, 143, 144, 0, 0, 240, 40
-"OGRE CHIEF ", 1, 0, 64, 9, 15, 2, 15, 238, 2, 28, 0, 131, 0, 148, 0, 160, 19
-"PANTHRO MIST ", 6, 5, 40, 7, 8, 4, 18, 88, 2, 0, 0, 3, 0, 0, 0, 16, 33
-"PHANTOM ", 6, 0, 35, 7, 8, 2, 10, 88, 2, 0, 0, 3, 145, 0, 0, 16, 63
-"SWORDSMAN ", 6, 5, 40, 6, 10, 2, 18, 88, 2, 20, 0, 3, 0, 143, 0, 166, 55
-"TROLL ", 6, 0, 40, 6, 9, 3, 12, 88, 2, 12, 0, 131, 0, 0, 0, 224, 17
-"WOOD GOLEM ", 3, 0, 30, 5, 15, 2, 5, 32, 3, 1, 0, 191, 0, 0, 0, 176, 16
-"WRAITH ", 6, 0, 35, 6, 6, 2, 9, 32, 3, 0, 0, 135, 14, 0, 0, 176, 60
-"YETI ", 6, 5, 50, 4, 10, 2, 13, 88, 2, 10, 0, 3, 0, 148, 0, 24, 31
-"DEADLY SPORES ", 15, 0, 10, 2, 1, 1, 10, 88, 2, 0, 0, 3, 4, 12, 90, 54, 48
-"ENCHANTRESS ", 2, 1, 30, 6, 6, 2, 15, 232, 3, 37, 0, 3, 136, 13, 80, 26, 54
-"FIRE LIZARD ", 4, 1, 40, 7, 10, 3, 12, 32, 3, 0, 0, 67, 0, 3, 20, 166, 36
-"GIANT SLOTH ", 3, 70, 40, 5, 8, 4, 14, 238, 2, 8, 0, 19, 0, 0, 0, 0, 31
-"GRIFFIN ", 8, 10, 45, 7, 8, 3, 14, 188, 2, 28, 0, 3, 143, 0, 0, 16, 28
-"PYRO HYDRA ", 1, 0, 60, 7, 8, 5, 12, 208, 7, 96, 0, 195, 0, 14, 50, 164, 44
-"MAN EATING MARE", 4, 0, 42, 6, 8, 3, 14, 88, 2, 52, 0, 3, 0, 0, 0, 32, 39
-"MANTICORE ", 4, 1, 40, 6, 6, 4, 12, 88, 2, 28, 0, 3, 0, 3, 20, 42, 26
-"MEDUSA ", 2, 1, 32, 5, 4, 1, 9, 232, 3, 0, 0, 135, 143, 15, 20, 36, 12
-"RAKSHASHA ", 4, 5, 40, 14, 5, 3, 14, 184, 11, 255, 50, 255, 142, 13, 80, 31, 11
-"STONE GOLEM ", 3, 0, 50, 7, 40, 1, 6, 220, 5, 1, 20, 255, 0, 0, 0, 48, 16
-"CAVE TROLL ", 6, 1, 50, 7, 11, 3, 10, 132, 3, 28, 0, 163, 0, 0, 0, 96, 17
-"HILL TROLL ", 5, 2, 50, 8, 12, 3, 11, 76, 4, 10, 0, 179, 0, 0, 0, 96, 17
-"WARLOCK ", 4, 60, 40, 8, 8, 1, 16, 32, 3, 21, 0, 3, 0, 16, 95, 26, 52
-"WEREBEAR ", 4, 10, 45, 8, 8, 4, 14, 32, 3, 0, 0, 135, 137, 0, 0, 160, 31
-"WICKED WITCH ", 4, 50, 30, 4, 6, 2, 14, 232, 3, 3, 0, 3, 151, 10, 40, 26, 12
-"ASSASSIN ", 4, 0, 45, 6, 8, 1, 19, 208, 7, 48, 0, 3, 146, 153, 0, 166, 57
-"BANSHEE ", 2, 1, 40, 10, 10, 1, 12, 184, 11, 0, 128, 135, 145, 8, 40, 52, 62
-"CAVE GIANT ", 6, 5, 50, 10, 16, 3, 12, 208, 7, 60, 0, 3, 0, 158, 0, 42, 17
-"CHIMERA ", 4, 1, 60, 8, 5, 6, 14, 136, 19, 28, 0, 127, 0, 14, 40, 35, 26
-"AIR ELEMENTAL ", 1, 5, 70, 7, 15, 1, 20, 160, 15, 0, 20, 175, 147, 17, 30, 180, 27
-"EXECUTIONER ", 1, 0, 60, 8, 12, 2, 14, 160, 15, 28, 0, 3, 146, 0, 0, 160, 57
-"GORGON ", 4, 5, 55, 8, 12, 1, 12, 112, 23, 0, 0, 3, 143, 11, 40, 35, 45
-"LESSER DEMON ", 4, 0, 40, 10, 8, 4, 16, 196, 9, 125, 20, 255, 145, 9, 15, 244, 59
-"LESSER DEVIL ", 4, 0, 40, 8, 6, 5, 16, 196, 9, 125, 20, 255, 145, 9, 25, 244, 59
-"MUMMY ", 6, 0, 50, 7, 20, 2, 7, 208, 7, 96, 128, 191, 9, 0, 0, 48, 61
-"NECROMANCER ", 4, 1, 35, 7, 8, 2, 17, 208, 7, 63, 40, 3, 0, 18, 95, 42, 54
-"SPECTER ", 6, 0, 47, 8, 12, 1, 12, 184, 11, 0, 128, 143, 17, 0, 0, 48, 58
-"WHITE WOLF ", 6, 0, 42, 10, 12, 3, 14, 196, 9, 4, 0, 19, 9, 27, 30, 50, 29
-"WYVERN ", 6, 5, 45, 7, 18, 2, 12, 208, 7, 38, 0, 3, 149, 0, 0, 32, 46
-"GREEN DRAGON ", 2, 0, 55, 8, 8, 3, 12, 112, 23, 63, 20, 255, 12, 25, 50, 163, 43
-"BLUE DRAGON ", 3, 5, 50, 8, 10, 3, 13, 112, 23, 63, 20, 255, 12, 26, 50, 163, 43
-"EVIL EYE ", 2, 0, 65, 10, 10, 2, 10, 136, 19, 103, 20, 255, 143, 21, 60, 38, 21
-"EARTH ELEMENTAL", 1, 5, 80, 8, 20, 1, 18, 160, 15, 0, 0, 215, 147, 17, 35, 180, 27
-"GHOST ", 3, 0, 60, 10, 10, 1, 10, 160, 15, 0, 128, 135, 16, 0, 0, 48, 62
-"FROST GIANT ", 6, 0, 70, 10, 24, 1, 12, 136, 19, 62, 0, 147, 0, 148, 0, 166, 23
-"STONE GIANT ", 6, 2, 80, 10, 10, 4, 12, 160, 15, 62, 0, 131, 0, 148, 0, 166, 19
-"8 HEADED HYDRA ", 1, 0, 75, 10, 8, 8, 13, 76, 29, 116, 0, 131, 0, 14, 35, 162, 44
-"LAVA BEAST ", 6, 0, 50, 5, 12, 2, 9, 160, 15, 0, 0, 231, 0, 14, 20, 35, 20
-"MANTIS WARRIOR ", 3, 0, 70, 8, 12, 4, 16, 160, 15, 68, 0, 131, 12, 0, 0, 160, 4
-"NAGA ", 3, 0, 65, 8, 8, 1, 15, 160, 15, 60, 25, 131, 136, 8, 40, 22, 35
-"DINOBEETLE ", 4, 0, 200, 10, 50, 1, 8, 112, 23, 28, 0, 131, 0, 0, 0, 160, 3
-"SPHINX ", 2, 50, 60, 11, 10, 3, 18, 136, 19, 63, 40, 255, 7, 8, 40, 22, 34
-"VAMPIRE ", 4, 0, 55, 9, 12, 2, 14, 136, 19, 61, 138, 135, 145, 13, 50, 246, 59
-"WARRIOR ", 4, 1, 75, 12, 12, 2, 14, 160, 15, 38, 0, 131, 0, 148, 0, 168, 50
-"WIZARD ", 2, 1, 60, 8, 6, 2, 18, 88, 27, 39, 0, 139, 0, 19, 95, 42, 52
-"WHITE DRAGON ", 3, 0, 65, 8, 12, 3, 15, 16, 39, 127, 30, 255, 0, 27, 60, 163, 42
-"GRAY DRAGON ", 3, 2, 70, 8, 15, 3, 16, 16, 39, 127, 30, 255, 0, 28, 60, 163, 42
-"ARCH DRUID ", 1, 5, 65, 10, 8, 2, 18, 152, 58, 29, 0, 255, 151, 20, 90, 34, 53
-"CHAOTIC KNIGHT ", 2, 0, 90, 14, 15, 3, 18, 88, 27, 134, 20, 135, 148, 158, 0, 250, 61
-"GREATER DEMON ", 2, 0, 60, 15, 8, 7, 19, 16, 39, 127, 30, 255, 21, 13, 25, 250, 13
-"GREATER DEVIL ", 2, 0, 65, 12, 15, 4, 19, 16, 39, 127, 30, 255, 21, 13, 35, 250, 13
-"FIRE ELEMENTAL ", 1, 5, 90, 9, 30, 1, 20, 64, 31, 0, 0, 199, 147, 17, 40, 180, 27
-"GUARDIAN SPIRIT", 2, 0, 60, 8, 6, 6, 16, 112, 23, 0, 128, 135, 17, 0, 0, 48, 64
-"STORM GIANT ", 4, 1, 100, 9, 30, 2, 14, 16, 39, 198, 0, 167, 0, 19, 40, 38, 23
-"12 HEADED HYDRA", 1, 0, 70, 10, 10, 12, 16, 224, 46, 127, 0, 131, 0, 14, 25, 162, 44
-"INVISIBLE THING", 4, 2, 50, 14, 10, 3, 25, 112, 23, 0, 0, 255, 22, 0, 0, 32, 58
-"MAGE ", 2, 1, 60, 10, 6, 3, 20, 64, 31, 39, 20, 143, 0, 21, 95, 42, 52
-"MASTER THIEF ", 2, 1, 65, 12, 8, 2, 20, 136, 19, 62, 0, 131, 23, 148, 0, 42, 49
-"STEEL GOLEM ", 2, 0, 70, 15, 25, 2, 10, 76, 29, 129, 30, 255, 0, 0, 0, 176, 61
-"WEREPHASE MUMMY", 4, 1, 70, 20, 20, 2, 35, 64, 31, 1, 50, 255, 9, 0, 0, 240, 61
-"BLACK DRAGON ", 2, 0, 75, 12, 18, 3, 16, 152, 58, 127, 30, 255, 135, 29, 70, 163, 41
-"RED DRAGON ", 2, 2, 80, 12, 20, 3, 15, 152, 58, 127, 30, 255, 141, 30, 70, 163, 41
-"XX!XX!XX!XX!XX ", 2, 0, 10, 20, 1, 1, 18, 152, 58, 0, 50, 255, 151, 0, 0, 0, 9
-"BLACK KNIGHT ", 1, 0, 150, 16, 50, 3, 20, 16, 39, 134, 30, 255, 14, 168, 0, 246, 56
-"DEMON LORD ", 1, 0, 150, 20, 50, 2, 30, 96, 234, 255, 50, 255, 24, 23, 20, 246, 13
-"ARCH DEVIL ", 1, 0, 200, 16, 100, 1, 30, 96, 234, 255, 50, 255, 24, 23, 30, 246, 13
-"GOLD DRAGON ", 1, 10, 150, 10, 20, 5, 16, 80, 195, 255, 40, 255, 136, 31, 80, 180, 41
-"SILVER DRAGON ", 2, 0, 90, 8, 16, 4, 16, 32, 78, 255, 40, 255, 136, 31, 80, 180, 41
-"DIAMOND GOLEM ", 2, 0, 100, 15, 60, 3, 12, 152, 58, 1, 40, 255, 0, 0, 0, 48, 16
-"16 HEADED HYDRA", 1, 0, 100, 15, 12, 16, 12, 32, 78, 255, 20, 255, 0, 29, 25, 246, 44
-"HIGH CLERIC ", 1, 5, 100, 14, 16, 3, 18, 16, 39, 127, 20, 131, 0, 22, 80, 36, 54
-"KIRIN ", 1, 50, 90, 15, 40, 4, 22, 176, 54, 135, 30, 255, 25, 9, 25, 42, 26
-"LICH ", 1, 0, 80, 10, 10, 2, 20, 32, 78, 135, 218, 255, 17, 23, 90, 54, 65
-"ARCH MAGE ", 1, 0, 70, 12, 8, 2, 25, 168, 97, 63, 30, 255, 0, 24, 95, 42, 52
-"MASTER ARCHER ", 1, 5, 120, 10, 16, 8, 18, 168, 97, 199, 20, 255, 150, 250, 0, 47, 51
-"PHOENIX ", 1, 50, 150, 13, 8, 3, 24, 152, 58, 129, 10, 255, 144, 14, 60, 42, 27
-"ROC ", 2, 20, 130, 10, 50, 3, 14, 152, 58, 0, 0, 255, 0, 0, 0, 32, 39
-"SAND WORM ", 3, 1, 200, 7, 200, 1, 8, 152, 58, 129, 0, 143, 146, 0, 0, 176, 35
-"TITAN ", 1, 50, 180, 13, 60, 2, 30, 32, 78, 255, 95, 255, 0, 250, 0, 122, 36
-"ALGAE BEAST ", 15, 0, 1, 0, 6, 1, 1, 50, 0, 0, 0, 7, 130, 0, 0, 16, 20
-"WATER RAT ", 15, 0, 3, 1, 6, 1, 6, 100, 0, 0, 0, 6, 130, 0, 0, 16, 6
-"LAMPREY ", 10, 0, 10, 2, 8, 1, 15, 200, 0, 0, 0, 7, 131, 0, 0, 32, 35
-"GIANT LEECH ", 6, 0, 10, 2, 8, 1, 3, 250, 0, 0, 0, 7, 132, 0, 0, 32, 75
-"CROCODILE ", 8, 0, 30, 5, 10, 2, 12, 44, 1, 0, 0, 6, 0, 0, 0, 160, 75
-"GIANT CRAB ", 6, 0, 25, 9, 10, 2, 12, 44, 1, 0, 0, 7, 0, 0, 0, 32, 0
-"BARRACUDA ", 15, 0, 20, 5, 20, 1, 16, 94, 1, 0, 0, 7, 0, 0, 0, 48, 75
-"GIANT SQUID ", 4, 0, 30, 5, 6, 8, 14, 144, 1, 0, 0, 7, 136, 6, 20, 38, 75
-"ELECTRIC EEL ", 10, 0, 30, 5, 8, 1, 15, 244, 1, 0, 0, 47, 136, 10, 20, 47, 75
-"SEA HAG ", 6, 0, 40, 8, 6, 3, 12, 244, 1, 0, 20, 15, 12, 15, 30, 102, 12
-"HIPPOCAMPUS ", 8, 0, 50, 12, 10, 4, 18, 88, 2, 0, 20, 15, 7, 0, 0, 224, 38
-"SHARK ", 15, 0, 40, 6, 30, 2, 24, 188, 2, 0, 0, 15, 0, 0, 0, 176, 75
-"SIREN ", 8, 0, 30, 8, 8, 2, 13, 188, 2, 0, 20, 255, 143, 7, 20, 102, 64
-"WATER ELEMENTAL", 6, 0, 80, 12, 50, 1, 30, 176, 4, 0, 20, 255, 0, 17, 50, 247, 9
-"SEA SERPENT ", 3, 32, 100, 10, 100, 1, 20, 184, 11, 0, 40, 143, 146, 0, 0, 240, 42
-"SEA DRAGON ", 3, 32, 150, 15, 50, 4, 32, 32, 78, 0, 50, 255, 8, 31, 50, 243, 42
-"SCORPION ", 1, 0, 210, 12, 60, 2, 20, 224, 46, 0, 50, 207, 12, 0, 0, 240, 1
-"DARK RIDER ", 1, 0, 210, 15, 50, 4, 30, 224, 46, 0, 90, 127, 17, 19, 20, 255, 56
-"WINGED BEAST ", 1, 0, 210, 12, 120, 1, 30, 224, 46, 0, 50, 159, 8, 0, 0, 240, 46
-"GREAT SEA BEAST", 1, 0, 210, 12, 100, 1, 30, 224, 46, 0, 50, 143, 147, 0, 0, 240, 75
-"DEMON KING ", 1, 0, 240, 30, 50, 5, 35, 80, 195, 255, 120, 255, 24, 23, 30, 255, 73
-"SUCCUBUS QUEEN ", 1, 0, 150, 20, 30, 3, 20, 16, 39, 127, 100, 239, 147, 21, 50, 255, 74
-"TYRANNOSAURUS ", 3, 0, 240, 10, 200, 1, 12, 136, 19, 6, 0, 7, 147, 0, 0, 160, 45
-"ALIEN ", 6, 16, 100, 15, 20, 2, 15, 232, 3, 1, 40, 7, 149, 24, 30, 35, 4
-"NATIVES ", 15, 21, 40, 6, 10, 2, 10, 200, 0, 3, 0, 3, 132, 32, 20, 163, 7
-"VOLCANO GOD ", 1, 0, 220, 30, 40, 6, 32, 96, 234, 255, 120, 255, 24, 13, 50, 255, 20
-"PAUL PEAD ", 1, 0, 100, 10, 30, 1, 19, 208, 7, 61, 50, 143, 14, 13, 40, 243, 50
-"PIRATE ", 15, 0, 40, 8, 20, 1, 17, 244, 1, 7, 10, 135, 138, 0, 0, 176, 58
-"PIRATE CAPTAIN ", 1, 0, 80, 10, 20, 3, 18, 232, 3, 15, 30, 135, 11, 7, 20, 51, 58
-"GRAY MINOTAUR ", 1, 0, 150, 13, 30, 4, 20, 152, 58, 63, 40, 143, 7, 10, 30, 255, 40
-"LORD ARCHER ", 1, 0, 32, 15, 80, 3, 21, 32, 78, 63, 100, 207, 6, 250, 0, 255, 51
-"BRONTASAURUS ", 3, 16, 200, 8, 150, 1, 6, 136, 19, 6, 0, 7, 147, 0, 0, 160, 45
-"STEGOSAURUS ", 3, 5, 200, 15, 200, 1, 6, 136, 19, 6, 0, 7, 147, 0, 0, 160, 45
-"KILLER CADAVER ", 3, 1, 50, 8, 12, 3, 15, 220, 5, 255, 0, 1, 9, 0, 0, 240, 65
-"OKRIM ", 2, 1, 80, 11, 6, 4, 18, 32, 78, 39, 0, 139, 0, 19, 95, 42, 52
+"FLESH EATER ", 6, 0, 2, 2, 6, 1, 7, 50, 0, 0, 0, 130, 0, 0, 16, 4
+"BATTLE RAT ", 10, 1, 1, 3, 3, 1, 12, 50, 2, 0, 0, 130, 0, 0, 0, 6
+"SLITHER BEAST ", 6, 0, 2, 4, 8, 1, 10, 125, 0, 0, 0, 0, 0, 0, 0, 35
+"GNOME ", 6, 50, 3, 5, 6, 1, 12, 125, 2, 20, 1, 0, 132, 0, 6, 8
+"GOBLIN ", 12, 0, 1, 4, 6, 1, 10, 50, 2, 0, 0, 0, 131, 0, 4, 15
+"GREMLIN ", 6, 1, 1, 3, 3, 2, 4, 125, 10, 0, 4, 129, 0, 0, 0, 10
+"GUARDSMAN ", 6, 10, 0, 2, 6, 1, 14, 75, 2, 0, 0, 0, 134, 0, 150, 55
+"KOBOLD ", 10, 1, 1, 4, 4, 1, 6, 50, 2, 0, 0, 0, 131, 0, 4, 5
+"MUTANT LARVA ", 6, 0, 0, 0, 3, 1, 2, 50, 0, 0, 7, 130, 0, 0, 0, 20
+"ORC ", 12, 5, 2, 4, 6, 1, 11, 75, 10, 0, 0, 0, 134, 0, 22, 14
+"POLTERGEIST ", 6, 0, 1, 0, 2, 2, 16, 150, 0, 128, 7, 131, 0, 0, 160, 60
+"RABID JACKAL ", 6, 0, 0, 3, 2, 1, 15, 50, 0, 0, 0, 130, 0, 0, 16, 29
+"SKELETON ", 12, 0, 1, 3, 6, 1, 9, 50, 2, 128, 7, 0, 0, 0, 160, 63
+"SNAKE ", 6, 0, 0, 2, 3, 1, 17, 125, 0, 0, 0, 132, 0, 0, 16, 35
+"SPRITE ", 8, 60, 0, 10, 2, 1, 20, 250, 11, 30, 1, 133, 1, 50, 8, 9
+"VAMPIRE BAT ", 8, 0, 0, 2, 3, 1, 14, 125, 0, 0, 0, 134, 0, 0, 16, 24
+"MINOR DEMON ", 10, 0, 10, 5, 8, 2, 16, 200, 5, 20, 15, 135, 2, 25, 218, 11
+"DEMON DOG ", 10, 3, 8, 3, 10, 2, 14, 100, 0, 0, 0, 0, 0, 0, 16, 32
+"DUNG BEETLE ", 6, 1, 8, 6, 8, 1, 8, 100, 8, 0, 1, 130, 0, 0, 16, 1
+"FIRE ANT ", 15, 0, 5, 5, 6, 1, 7, 100, 26, 0, 67, 0, 3, 10, 20, 0
+"GHOUL ", 6, 0, 8, 4, 5, 3, 13, 200, 5, 128, 7, 136, 0, 0, 16, 58
+"GNOLL ", 10, 0, 8, 5, 8, 1, 10, 100, 10, 0, 0, 0, 134, 0, 6, 15
+"HAG ", 2, 0, 3, 1, 4, 2, 8, 100, 1, 0, 0, 138, 4, 20, 20, 12
+"LOCUST PLAGUE ", 4, 0, 8, 5, 1, 10, 17, 200, 0, 0, 7, 130, 32, 10, 47, 2
+"ORC LEADER ", 1, 0, 10, 5, 8, 1, 14, 100, 28, 0, 0, 0, 138, 0, 38, 14
+"RABID LEPER ", 4, 0, 5, 0, 3, 1, 11, 100, 0, 0, 0, 137, 0, 0, 16, 65
+"ROTTING CORPSE ", 6, 0, 8, 2, 4, 2, 3, 100, 0, 128, 7, 137, 0, 0, 16, 65
+"SAVAGE SHREW ", 4, 5, 4, 3, 5, 3, 13, 150, 0, 0, 0, 0, 0, 0, 0, 32
+"STRANGLING VINE", 10, 0, 1, 3, 3, 4, 6, 100, 40, 0, 3, 134, 0, 0, 51, 47
+"THIEF ", 8, 0, 6, 3, 8, 1, 16, 100, 20, 0, 0, 139, 134, 0, 4, 49
+"TROGLODYTE ", 6, 1, 8, 5, 4, 3, 11, 100, 10, 0, 3, 132, 5, 20, 22, 37
+"ZOMBIE ", 8, 0, 8, 2, 8, 1, 2, 100, 0, 128, 7, 130, 0, 0, 32, 7
+"ACIDIC BLOB ", 6, 0, 8, 1, 8, 2, 8, 300, 0, 0, 127, 140, 6, 20, 118, 20
+"CENTAUR ", 12, 60, 20, 4, 4, 4, 12, 200, 27, 0, 3, 0, 7, 20, 20, 18
+"CLERIC ", 4, 10, 15, 5, 8, 1, 12, 300, 11, 0, 0, 0, 8, 50, 20, 53
+"MINOR DEVIL ", 10, 0, 15, 4, 4, 2, 15, 250, 61, 20, 15, 136, 2, 30, 234, 11
+"FIRE BEETLE ", 5, 0, 16, 7, 15, 1, 6, 200, 2, 0, 65, 0, 3, 30, 22, 1
+"GARGOYLE ", 6, 0, 24, 5, 4, 4, 12, 300, 3, 20, 15, 136, 0, 0, 16, 11
+"GARGANTUAN ANT ", 6, 0, 18, 8, 12, 1, 9, 200, 24, 0, 3, 0, 0, 0, 160, 0
+"DINOLIZARD ", 6, 0, 16, 5, 10, 1, 11, 200, 0, 0, 3, 0, 0, 0, 16, 36
+"GIANT SPIDER ", 6, 1, 20, 5, 8, 1, 18, 200, 1, 0, 1, 140, 0, 0, 16, 0
+"HARPY ", 6, 0, 15, 3, 5, 3, 15, 200, 28, 0, 3, 0, 8, 10, 20, 25
+"HIPPOGRIFF ", 6, 5, 18, 5, 8, 3, 14, 200, 12, 0, 0, 138, 0, 0, 16, 39
+"KILLER BEES ", 4, 0, 10, 10, 2, 10, 16, 300, 0, 0, 7, 132, 32, 20, 42, 2
+"PEGASUS ", 6, 90, 25, 4, 8, 3, 20, 250, 27, 10, 15, 135, 9, 10, 4, 38
+"SHADOW BEAST ", 6, 0, 20, 3, 5, 1, 18, 200, 0, 0, 15, 141, 0, 0, 32, 60
+"WILD BOAR ", 6, 5, 15, 3, 12, 1, 14, 200, 0, 0, 0, 0, 0, 0, 16, 32
+"WOLVERINE ", 3, 0, 10, 5, 5, 3, 12, 250, 10, 0, 1, 0, 0, 0, 16, 29
+"BARBARIAN ", 10, 5, 50, 8, 12, 2, 15, 400, 12, 20, 1, 0, 140, 0, 170, 23
+"CARYATID GUARD ", 6, 2, 20, 5, 10, 1, 15, 400, 1, 25, 255, 142, 9, 10, 54, 64
+"COCKATRICE ", 6, 3, 28, 4, 8, 1, 8, 500, 0, 0, 3, 143, 0, 0, 16, 28
+"CYCLOPS ", 8, 1, 32, 6, 15, 2, 10, 400, 28, 0, 1, 0, 148, 0, 168, 22
+"DRUID ", 4, 2, 24, 4, 8, 2, 14, 400, 3, 0, 1, 138, 7, 50, 22, 53
+"RHINO BEETLE ", 4, 0, 25, 7, 20, 1, 7, 500, 24, 0, 3, 0, 6, 30, 35, 3
+"GIANT CENTIPEDE", 4, 0, 15, 5, 4, 8, 9, 500, 2, 0, 3, 136, 0, 0, 32, 1
+"MAGICIAN ", 3, 1, 25, 5, 8, 1, 15, 600, 29, 0, 1, 0, 10, 90, 24, 52
+"MILITIAMAN ", 6, 10, 30, 9, 10, 2, 9, 300, 2, 0, 1, 0, 138, 0, 150, 50
+"ORC CHIEFTAIN ", 1, 0, 60, 10, 12, 2, 15, 500, 28, 0, 1, 136, 140, 0, 170, 14
+"OGRE ", 6, 0, 45, 7, 10, 2, 12, 350, 12, 0, 1, 0, 140, 0, 170, 19
+"SATYR ", 5, 50, 28, 5, 8, 2, 10, 300, 26, 0, 15, 135, 8, 40, 24, 18
+"SWARMING WASPS ", 4, 0, 20, 4, 2, 10, 17, 400, 0, 0, 7, 132, 32, 25, 47, 2
+"UNICORN ", 4, 90, 35, 8, 10, 3, 22, 500, 7, 20, 127, 141, 9, 20, 69, 38
+"WEREWOLF ", 4, 10, 30, 7, 8, 2, 14, 400, 0, 0, 7, 137, 0, 0, 144, 30
+"WIGHT ", 6, 0, 20, 6, 10, 1, 12, 500, 0, 128, 7, 142, 0, 0, 160, 60
+"BARBARIAN CHIEF", 1, 0, 80, 10, 12, 3, 18, 800, 28, 0, 3, 0, 143, 0, 184, 23
+"BASILISK ", 4, 2, 30, 5, 15, 1, 14, 1000, 0, 0, 3, 143, 11, 30, 163, 45
+"CELESTIAL STAG ", 2, 1, 50, 14, 10, 3, 19, 700, 34, 0, 3, 0, 0, 0, 32, 39
+"DUST DEMON ", 3, 0, 30, 9, 12, 3, 15, 600, 1, 0, 15, 7, 7, 20, 154, 34
+"GIANT SCORPION ", 4, 0, 30, 7, 8, 3, 13, 600, 0, 0, 3, 12, 0, 0, 32, 0
+"5 HEADED HYDRA ", 1, 0, 80, 7, 8, 5, 12, 1500, 60, 0, 3, 0, 14, 40, 160, 44
+"WARRIOR CAT ", 4, 5, 40, 6, 6, 4, 17, 600, 0, 0, 3, 0, 0, 0, 16, 33
+"MINOTAUR ", 2, 0, 55, 7, 35, 1, 15, 1500, 60, 20, 143, 144, 0, 0, 240, 40
+"OGRE CHIEF ", 1, 0, 64, 9, 15, 2, 15, 750, 28, 0, 131, 0, 148, 0, 160, 19
+"PANTHRO MIST ", 6, 5, 40, 7, 8, 4, 18, 600, 0, 0, 3, 0, 0, 0, 16, 33
+"PHANTOM ", 6, 0, 35, 7, 8, 2, 10, 600, 0, 0, 3, 145, 0, 0, 16, 63
+"SWORDSMAN ", 6, 5, 40, 6, 10, 2, 18, 600, 20, 0, 3, 0, 143, 0, 166, 55
+"TROLL ", 6, 0, 40, 6, 9, 3, 12, 600, 12, 0, 131, 0, 0, 0, 224, 17
+"WOOD GOLEM ", 3, 0, 30, 5, 15, 2, 5, 800, 1, 0, 191, 0, 0, 0, 176, 16
+"WRAITH ", 6, 0, 35, 6, 6, 2, 9, 800, 0, 0, 135, 14, 0, 0, 176, 60
+"YETI ", 6, 5, 50, 4, 10, 2, 13, 600, 10, 0, 3, 0, 148, 0, 24, 31
+"DEADLY SPORES ", 15, 0, 10, 2, 1, 1, 10, 600, 0, 0, 3, 4, 12, 90, 54, 48
+"ENCHANTRESS ", 2, 1, 30, 6, 6, 2, 15, 1000, 37, 0, 3, 136, 13, 80, 26, 54
+"FIRE LIZARD ", 4, 1, 40, 7, 10, 3, 12, 800, 0, 0, 67, 0, 3, 20, 166, 36
+"GIANT SLOTH ", 3, 70, 40, 5, 8, 4, 14, 750, 8, 0, 19, 0, 0, 0, 0, 31
+"GRIFFIN ", 8, 10, 45, 7, 8, 3, 14, 700, 28, 0, 3, 143, 0, 0, 16, 28
+"PYRO HYDRA ", 1, 0, 60, 7, 8, 5, 12, 2000, 96, 0, 195, 0, 14, 50, 164, 44
+"MAN EATING MARE", 4, 0, 42, 6, 8, 3, 14, 600, 52, 0, 3, 0, 0, 0, 32, 39
+"MANTICORE ", 4, 1, 40, 6, 6, 4, 12, 600, 28, 0, 3, 0, 3, 20, 42, 26
+"MEDUSA ", 2, 1, 32, 5, 4, 1, 9, 1000, 0, 0, 135, 143, 15, 20, 36, 12
+"RAKSHASHA ", 4, 5, 40, 14, 5, 3, 14, 3000, 255, 50, 255, 142, 13, 80, 31, 11
+"STONE GOLEM ", 3, 0, 50, 7, 40, 1, 6, 1500, 1, 20, 255, 0, 0, 0, 48, 16
+"CAVE TROLL ", 6, 1, 50, 7, 11, 3, 10, 900, 28, 0, 163, 0, 0, 0, 96, 17
+"HILL TROLL ", 5, 2, 50, 8, 12, 3, 11, 1100, 10, 0, 179, 0, 0, 0, 96, 17
+"WARLOCK ", 4, 60, 40, 8, 8, 1, 16, 800, 21, 0, 3, 0, 16, 95, 26, 52
+"WEREBEAR ", 4, 10, 45, 8, 8, 4, 14, 800, 0, 0, 135, 137, 0, 0, 160, 31
+"WICKED WITCH ", 4, 50, 30, 4, 6, 2, 14, 1000, 3, 0, 3, 151, 10, 40, 26, 12
+"ASSASSIN ", 4, 0, 45, 6, 8, 1, 19, 2000, 48, 0, 3, 146, 153, 0, 166, 57
+"BANSHEE ", 2, 1, 40, 10, 10, 1, 12, 3000, 0, 128, 135, 145, 8, 40, 52, 62
+"CAVE GIANT ", 6, 5, 50, 10, 16, 3, 12, 2000, 60, 0, 3, 0, 158, 0, 42, 17
+"CHIMERA ", 4, 1, 60, 8, 5, 6, 14, 5000, 28, 0, 127, 0, 14, 40, 35, 26
+"AIR ELEMENTAL ", 1, 5, 70, 7, 15, 1, 20, 4000, 0, 20, 175, 147, 17, 30, 180, 27
+"EXECUTIONER ", 1, 0, 60, 8, 12, 2, 14, 4000, 28, 0, 3, 146, 0, 0, 160, 57
+"GORGON ", 4, 5, 55, 8, 12, 1, 12, 6000, 0, 0, 3, 143, 11, 40, 35, 45
+"LESSER DEMON ", 4, 0, 40, 10, 8, 4, 16, 2500, 125, 20, 255, 145, 9, 15, 244, 59
+"LESSER DEVIL ", 4, 0, 40, 8, 6, 5, 16, 2500, 125, 20, 255, 145, 9, 25, 244, 59
+"MUMMY ", 6, 0, 50, 7, 20, 2, 7, 2000, 96, 128, 191, 9, 0, 0, 48, 61
+"NECROMANCER ", 4, 1, 35, 7, 8, 2, 17, 2000, 63, 40, 3, 0, 18, 95, 42, 54
+"SPECTER ", 6, 0, 47, 8, 12, 1, 12, 3000, 0, 128, 143, 17, 0, 0, 48, 58
+"WHITE WOLF ", 6, 0, 42, 10, 12, 3, 14, 2500, 4, 0, 19, 9, 27, 30, 50, 29
+"WYVERN ", 6, 5, 45, 7, 18, 2, 12, 2000, 38, 0, 3, 149, 0, 0, 32, 46
+"GREEN DRAGON ", 2, 0, 55, 8, 8, 3, 12, 6000, 63, 20, 255, 12, 25, 50, 163, 43
+"BLUE DRAGON ", 3, 5, 50, 8, 10, 3, 13, 6000, 63, 20, 255, 12, 26, 50, 163, 43
+"EVIL EYE ", 2, 0, 65, 10, 10, 2, 10, 5000, 103, 20, 255, 143, 21, 60, 38, 21
+"EARTH ELEMENTAL", 1, 5, 80, 8, 20, 1, 18, 4000, 0, 0, 215, 147, 17, 35, 180, 27
+"GHOST ", 3, 0, 60, 10, 10, 1, 10, 4000, 0, 128, 135, 16, 0, 0, 48, 62
+"FROST GIANT ", 6, 0, 70, 10, 24, 1, 12, 5000, 62, 0, 147, 0, 148, 0, 166, 23
+"STONE GIANT ", 6, 2, 80, 10, 10, 4, 12, 4000, 62, 0, 131, 0, 148, 0, 166, 19
+"8 HEADED HYDRA ", 1, 0, 75, 10, 8, 8, 13, 7500, 116, 0, 131, 0, 14, 35, 162, 44
+"LAVA BEAST ", 6, 0, 50, 5, 12, 2, 9, 4000, 0, 0, 231, 0, 14, 20, 35, 20
+"MANTIS WARRIOR ", 3, 0, 70, 8, 12, 4, 16, 4000, 68, 0, 131, 12, 0, 0, 160, 4
+"NAGA ", 3, 0, 65, 8, 8, 1, 15, 4000, 60, 25, 131, 136, 8, 40, 22, 35
+"DINOBEETLE ", 4, 0, 200, 10, 50, 1, 8, 6000, 28, 0, 131, 0, 0, 0, 160, 3
+"SPHINX ", 2, 50, 60, 11, 10, 3, 18, 5000, 63, 40, 255, 7, 8, 40, 22, 34
+"VAMPIRE ", 4, 0, 55, 9, 12, 2, 14, 5000, 61, 138, 135, 145, 13, 50, 246, 59
+"WARRIOR ", 4, 1, 75, 12, 12, 2, 14, 4000, 38, 0, 131, 0, 148, 0, 168, 50
+"WIZARD ", 2, 1, 60, 8, 6, 2, 18, 7000, 39, 0, 139, 0, 19, 95, 42, 52
+"WHITE DRAGON ", 3, 0, 65, 8, 12, 3, 15, 10000, 127, 30, 255, 0, 27, 60, 163, 42
+"GRAY DRAGON ", 3, 2, 70, 8, 15, 3, 16, 10000, 127, 30, 255, 0, 28, 60, 163, 42
+"ARCH DRUID ", 1, 5, 65, 10, 8, 2, 18, 15000, 29, 0, 255, 151, 20, 90, 34, 53
+"CHAOTIC KNIGHT ", 2, 0, 90, 14, 15, 3, 18, 7000, 134, 20, 135, 148, 158, 0, 250, 61
+"GREATER DEMON ", 2, 0, 60, 15, 8, 7, 19, 10000, 127, 30, 255, 21, 13, 25, 250, 13
+"GREATER DEVIL ", 2, 0, 65, 12, 15, 4, 19, 10000, 127, 30, 255, 21, 13, 35, 250, 13
+"FIRE ELEMENTAL ", 1, 5, 90, 9, 30, 1, 20, 8000, 0, 0, 199, 147, 17, 40, 180, 27
+"GUARDIAN SPIRIT", 2, 0, 60, 8, 6, 6, 16, 6000, 0, 128, 135, 17, 0, 0, 48, 64
+"STORM GIANT ", 4, 1, 100, 9, 30, 2, 14, 10000, 198, 0, 167, 0, 19, 40, 38, 23
+"12 HEADED HYDRA", 1, 0, 70, 10, 10, 12, 16, 12000, 127, 0, 131, 0, 14, 25, 162, 44
+"INVISIBLE THING", 4, 2, 50, 14, 10, 3, 25, 6000, 0, 0, 255, 22, 0, 0, 32, 58
+"MAGE ", 2, 1, 60, 10, 6, 3, 20, 8000, 39, 20, 143, 0, 21, 95, 42, 52
+"MASTER THIEF ", 2, 1, 65, 12, 8, 2, 20, 5000, 62, 0, 131, 23, 148, 0, 42, 49
+"STEEL GOLEM ", 2, 0, 70, 15, 25, 2, 10, 7500, 129, 30, 255, 0, 0, 0, 176, 61
+"WEREPHASE MUMMY", 4, 1, 70, 20, 20, 2, 35, 8000, 1, 50, 255, 9, 0, 0, 240, 61
+"BLACK DRAGON ", 2, 0, 75, 12, 18, 3, 16, 15000, 127, 30, 255, 135, 29, 70, 163, 41
+"RED DRAGON ", 2, 2, 80, 12, 20, 3, 15, 15000, 127, 30, 255, 141, 30, 70, 163, 41
+"XX!XX!XX!XX!XX ", 2, 0, 10, 20, 1, 1, 18, 15000, 0, 50, 255, 151, 0, 0, 0, 9
+"BLACK KNIGHT ", 1, 0, 150, 16, 50, 3, 20, 10000, 134, 30, 255, 14, 168, 0, 246, 56
+"DEMON LORD ", 1, 0, 150, 20, 50, 2, 30, 60000, 255, 50, 255, 24, 23, 20, 246, 13
+"ARCH DEVIL ", 1, 0, 200, 16, 100, 1, 30, 60000, 255, 50, 255, 24, 23, 30, 246, 13
+"GOLD DRAGON ", 1, 10, 150, 10, 20, 5, 16, 50000, 255, 40, 255, 136, 31, 80, 180, 41
+"SILVER DRAGON ", 2, 0, 90, 8, 16, 4, 16, 20000, 255, 40, 255, 136, 31, 80, 180, 41
+"DIAMOND GOLEM ", 2, 0, 100, 15, 60, 3, 12, 15000, 1, 40, 255, 0, 0, 0, 48, 16
+"16 HEADED HYDRA", 1, 0, 100, 15, 12, 16, 12, 20000, 255, 20, 255, 0, 29, 25, 246, 44
+"HIGH CLERIC ", 1, 5, 100, 14, 16, 3, 18, 10000, 127, 20, 131, 0, 22, 80, 36, 54
+"KIRIN ", 1, 50, 90, 15, 40, 4, 22, 14000, 135, 30, 255, 25, 9, 25, 42, 26
+"LICH ", 1, 0, 80, 10, 10, 2, 20, 20000, 135, 218, 255, 17, 23, 90, 54, 65
+"ARCH MAGE ", 1, 0, 70, 12, 8, 2, 25, 25000, 63, 30, 255, 0, 24, 95, 42, 52
+"MASTER ARCHER ", 1, 5, 120, 10, 16, 8, 18, 25000, 199, 20, 255, 150, 250, 0, 47, 51
+"PHOENIX ", 1, 50, 150, 13, 8, 3, 24, 15000, 129, 10, 255, 144, 14, 60, 42, 27
+"ROC ", 2, 20, 130, 10, 50, 3, 14, 15000, 0, 0, 255, 0, 0, 0, 32, 39
+"SAND WORM ", 3, 1, 200, 7, 200, 1, 8, 15000, 129, 0, 143, 146, 0, 0, 176, 35
+"TITAN ", 1, 50, 180, 13, 60, 2, 30, 20000, 255, 95, 255, 0, 250, 0, 122, 36
+"ALGAE BEAST ", 15, 0, 1, 0, 6, 1, 1, 50, 0, 0, 7, 130, 0, 0, 16, 20
+"WATER RAT ", 15, 0, 3, 1, 6, 1, 6, 100, 0, 0, 6, 130, 0, 0, 16, 6
+"LAMPREY ", 10, 0, 10, 2, 8, 1, 15, 200, 0, 0, 7, 131, 0, 0, 32, 35
+"GIANT LEECH ", 6, 0, 10, 2, 8, 1, 3, 250, 0, 0, 7, 132, 0, 0, 32, 75
+"CROCODILE ", 8, 0, 30, 5, 10, 2, 12, 300, 0, 0, 6, 0, 0, 0, 160, 75
+"GIANT CRAB ", 6, 0, 25, 9, 10, 2, 12, 300, 0, 0, 7, 0, 0, 0, 32, 0
+"BARRACUDA ", 15, 0, 20, 5, 20, 1, 16, 350, 0, 0, 7, 0, 0, 0, 48, 75
+"GIANT SQUID ", 4, 0, 30, 5, 6, 8, 14, 400, 0, 0, 7, 136, 6, 20, 38, 75
+"ELECTRIC EEL ", 10, 0, 30, 5, 8, 1, 15, 500, 0, 0, 47, 136, 10, 20, 47, 75
+"SEA HAG ", 6, 0, 40, 8, 6, 3, 12, 500, 0, 20, 15, 12, 15, 30, 102, 12
+"HIPPOCAMPUS ", 8, 0, 50, 12, 10, 4, 18, 600, 0, 20, 15, 7, 0, 0, 224, 38
+"SHARK ", 15, 0, 40, 6, 30, 2, 24, 700, 0, 0, 15, 0, 0, 0, 176, 75
+"SIREN ", 8, 0, 30, 8, 8, 2, 13, 700, 0, 20, 255, 143, 7, 20, 102, 64
+"WATER ELEMENTAL", 6, 0, 80, 12, 50, 1, 30, 1200, 0, 20, 255, 0, 17, 50, 247, 9
+"SEA SERPENT ", 3, 32, 100, 10, 100, 1, 20, 3000, 0, 40, 143, 146, 0, 0, 240, 42
+"SEA DRAGON ", 3, 32, 150, 15, 50, 4, 32, 20000, 0, 50, 255, 8, 31, 50, 243, 42
+"SCORPION ", 1, 0, 210, 12, 60, 2, 20, 12000, 0, 50, 207, 12, 0, 0, 240, 1
+"DARK RIDER ", 1, 0, 210, 15, 50, 4, 30, 12000, 0, 90, 127, 17, 19, 20, 255, 56
+"WINGED BEAST ", 1, 0, 210, 12, 120, 1, 30, 12000, 0, 50, 159, 8, 0, 0, 240, 46
+"GREAT SEA BEAST", 1, 0, 210, 12, 100, 1, 30, 12000, 0, 50, 143, 147, 0, 0, 240, 75
+"DEMON KING ", 1, 0, 240, 30, 50, 5, 35, 50000, 255, 120, 255, 24, 23, 30, 255, 73
+"SUCCUBUS QUEEN ", 1, 0, 150, 20, 30, 3, 20, 10000, 127, 100, 239, 147, 21, 50, 255, 74
+"TYRANNOSAURUS ", 3, 0, 240, 10, 200, 1, 12, 5000, 6, 0, 7, 147, 0, 0, 160, 45
+"ALIEN ", 6, 16, 100, 15, 20, 2, 15, 1000, 1, 40, 7, 149, 24, 30, 35, 4
+"NATIVES ", 15, 21, 40, 6, 10, 2, 10, 200, 3, 0, 3, 132, 32, 20, 163, 7
+"VOLCANO GOD ", 1, 0, 220, 30, 40, 6, 32, 60000, 255, 120, 255, 24, 13, 50, 255, 20
+"PAUL PEAD ", 1, 0, 100, 10, 30, 1, 19, 2000, 61, 50, 143, 14, 13, 40, 243, 50
+"PIRATE ", 15, 0, 40, 8, 20, 1, 17, 500, 7, 10, 135, 138, 0, 0, 176, 58
+"PIRATE CAPTAIN ", 1, 0, 80, 10, 20, 3, 18, 1000, 15, 30, 135, 11, 7, 20, 51, 58
+"GRAY MINOTAUR ", 1, 0, 150, 13, 30, 4, 20, 15000, 63, 40, 143, 7, 10, 30, 255, 40
+"LORD ARCHER ", 1, 0, 32, 15, 80, 3, 21, 20000, 63, 100, 207, 6, 250, 0, 255, 51
+"BRONTASAURUS ", 3, 16, 200, 8, 150, 1, 6, 5000, 6, 0, 7, 147, 0, 0, 160, 45
+"STEGOSAURUS ", 3, 5, 200, 15, 200, 1, 6, 5000, 6, 0, 7, 147, 0, 0, 160, 45
+"KILLER CADAVER ", 3, 1, 50, 8, 12, 3, 15, 1500, 255, 0, 1, 9, 0, 0, 240, 65
+"OKRIM ", 2, 1, 80, 11, 6, 4, 18, 20000, 39, 0, 139, 0, 19, 95, 42, 52
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 78a16eb91b6..0179871c66d 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -133,9 +133,10 @@ bool Console::cmdDumpMonsters(int argc, const char **argv) {
line += f.readByte();
line += '"';
- for (int j = 0; j < 17; ++j) {
+ for (int j = 0; j < 16; ++j) {
line += ", ";
- line += Common::String::format("%d", f.readByte());
+ int val = (j == 7) ? f.readUint16LE() : f.readByte();
+ line += Common::String::format("%d", val);
}
df.writeString(line);
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index 8335bbd7eaf..b9e52d955d6 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -107,7 +107,7 @@ public:
*/
const Monster &operator[](uint i) {
assert(i >= 1 && i <= MONSTERS_COUNT);
- return _monsters[i];
+ return _monsters[i - 1];
}
/**
diff --git a/engines/mm/mm1/game/encounter.cpp b/engines/mm/mm1/game/encounter.cpp
index 55175062f06..f25a4b27a49 100644
--- a/engines/mm/mm1/game/encounter.cpp
+++ b/engines/mm/mm1/game/encounter.cpp
@@ -48,7 +48,7 @@ void Encounter::execute() {
}
_totalLevels = _highestLevel = 0;
- _levelOffset = _monsterImgNum = _val9 = _fleeThreshold = 0;
+ _levelOffset = _monsterImgNum = _maxLevelForImg = _fleeThreshold = 0;
for (uint i = 0; i < g_globals->_party.size(); ++i) {
const Character &c = g_globals->_party[i];
@@ -121,7 +121,7 @@ exit_loop:
if (_monsterSummaries[i]._level < 1 || _monsterSummaries[i]._level > 12
|| maxVal >= 196) {
_monsterSummaries[i]._level = 10;
- _monsterSummaries[i]._num = getRandomNumber(MAX_COMBAT_MONSTERS);
+ _monsterSummaries[i]._num = getRandomNumber(15);
}
// Add monster details to list
@@ -131,8 +131,8 @@ exit_loop:
Monster &mons = _monsterList.back();
mons._level = _monsterSummaries[i]._level;
- if (_monsterLevel > _val9) {
- _val9 = _monsterLevel;
+ if (_monsterLevel > _maxLevelForImg) {
+ _maxLevelForImg = _monsterLevel;
_fleeThreshold = mons._fleeThreshold;
_monsterImgNum = mons._imgNum;
}
diff --git a/engines/mm/mm1/game/encounter.h b/engines/mm/mm1/game/encounter.h
index 1589aff9897..7d61d290268 100644
--- a/engines/mm/mm1/game/encounter.h
+++ b/engines/mm/mm1/game/encounter.h
@@ -40,7 +40,7 @@ enum EncounterType {
class Encounter : public GameLogic {
private:
int _levelOffset = 0;
- int _val9 = 0;
+ int _maxLevelForImg = 0;
int _monsterLevel = 0;
int _totalLevels = 0;
int _monsterNum = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 2adc057d116..de050544f1a 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -353,6 +353,7 @@ void Combat::writeOptions() {
}
void Combat::writeAllOptions() {
+ assert(g_globals->_currCharacter);
writeString(0, 20, STRING["dialogs.combat.options_for"]);
writeString(0, 22, g_globals->_currCharacter->_name);
Commit: 5e09a089ec46129982cb81214426e53ff4968488
https://github.com/scummvm/scummvm/commit/5e09a089ec46129982cb81214426e53ff4968488
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Add level parameter to encounter console cmd
Changed paths:
engines/mm/mm1/console.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 0179871c66d..6653fd87579 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -328,7 +328,7 @@ bool Console::cmdCast(int argc, const char **argv) {
bool Console::cmdEncounter(int argc, const char **argv) {
if (argc < 2) {
- debugPrintf("encounter <monster-num> [<encounter type>]\n");
+ debugPrintf("encounter <monster-num> [<level>, <encounter type>]\n");
return true;
} else {
@@ -338,14 +338,17 @@ bool Console::cmdEncounter(int argc, const char **argv) {
debugPrintf("monster-num must be between 1 and %d\n", MONSTERS_COUNT);
return true;
}
+ int level = (argc == 3) ? strToInt(argv[2]) : 1;
+ if (level < 1 || level >= 15)
+ level = 1;
- int encType = (argc > 2) ? strToInt(argv[2]) :
+ int encType = (argc > 3) ? strToInt(argv[2]) :
Game::NORMAL_ENCOUNTER;
if (encType != -1 || encType == 0 || encType == 1)
enc._encounterType = (Game::EncounterType)encType;
enc.clearMonsters();
- enc.addMonster(monsterNum, 1);
+ enc.addMonster(monsterNum, level);
enc._manual = true;
enc._levelIndex = 80;
Commit: 25ba84fe0d0c8f629ea84c19034428f2cedb3979
https://github.com/scummvm/scummvm/commit/25ba84fe0d0c8f629ea84c19034428f2cedb3979
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Cleanup of encounter methods
Changed paths:
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/encounter.h
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index a4efc7f34c4..1b69ada622b 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -62,7 +62,7 @@ void Encounter::draw() {
case SURPRISED_MONSTERS:
writeString(2, 21, STRING["dialogs.encounter.surprise"]);
- writeString(1, 22, STRING["dialogs.encounter.surprise"]);
+ writeString(1, 22, STRING["dialogs.encounter.approach"]);
break;
case ENCOUNTER_OPTIONS: {
@@ -152,7 +152,7 @@ void Encounter::timeout() {
switch (_mode) {
case ALERT:
// Finished displaying initial encounter alert
- if (enc._encounterType < 0 /* FORCE_SURPRISED */) {
+ if (enc._encounterType == Game::FORCE_SURPRISED) {
_mode = SURPRISED_BY_MONSTERS;
} else if (enc._encounterType == Game::NORMAL_SURPRISED ||
/* ENCOUNTER_OPTIONS */
diff --git a/engines/mm/mm1/views/encounter.h b/engines/mm/mm1/views/encounter.h
index d205c3d148e..cec9668bb00 100644
--- a/engines/mm/mm1/views/encounter.h
+++ b/engines/mm/mm1/views/encounter.h
@@ -46,12 +46,42 @@ private:
* Handles the end of the encounter
*/
void encounterEnded();
+
+ /**
+ * Initiates the combat
+ */
void attack();
+
+ /**
+ * Try and bribe the enemies
+ */
void bribe();
+
+ /**
+ * Try and retreat
+ */
void retreat();
+
+ /**
+ * Try and surrender
+ */
void surrender();
+
+ /**
+ * Ends an encounter
+ */
void flee();
+
+ /**
+ * Decreases the alignment counter, gradually turning
+ * EVIL to NEUTRAL to GOOD
+ */
void decreaseAlignments();
+
+ /**
+ * Increases the alignment counter, gradually turning
+ * GOOD to NEUTRAL to EVIL
+ */
void increaseAlignments();
public:
Encounter();
Commit: 75eec8a84eb5b7a7b41ab5d15c04f36b3c596661
https://github.com/scummvm/scummvm/commit/75eec8a84eb5b7a7b41ab5d15c04f36b3c596661
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Fixes for retreat and surrender in encounters
Changed paths:
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index 1b69ada622b..a2f6cf56dad 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -135,6 +135,7 @@ void Encounter::draw() {
if (_mode == NO_RESPONSE || _mode == SURROUNDED ||
_mode == NOT_ENOUGH || _mode == COMBAT ||
+ _mode == NOWHERE_TO_RUN || _mode == SURRENDER_FAILED ||
_mode == SURPRISED_BY_MONSTERS) {
if (enc._alignmentsChanged) {
writeString(8, 23, STRING["dialogs.encounter.alignment_slips"]);
Commit: f04d6e4fd06ce28c5c181d513c6e759fdbf5a990
https://github.com/scummvm/scummvm/commit/f04d6e4fd06ce28c5c181d513c6e759fdbf5a990
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Select a character by default on startup
Changed paths:
engines/mm/mm1/data/party.cpp
engines/mm/mm1/views/locations/inn.cpp
diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp
index a74791d19cd..ad7ffde5657 100644
--- a/engines/mm/mm1/data/party.cpp
+++ b/engines/mm/mm1/data/party.cpp
@@ -146,6 +146,9 @@ void Party::synchronize(Common::Serializer &s) {
for (int i = 0; i < partySize; ++i)
(*this)[i].synchronize(s);
+
+ if (s.isLoading())
+ g_globals->_currCharacter = &front();
}
void Party::rearrange(const Common::Array<Character *> &party) {
diff --git a/engines/mm/mm1/views/locations/inn.cpp b/engines/mm/mm1/views/locations/inn.cpp
index c3c44e9f79e..fde5edefc79 100644
--- a/engines/mm/mm1/views/locations/inn.cpp
+++ b/engines/mm/mm1/views/locations/inn.cpp
@@ -130,6 +130,7 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
for (uint i = 0; i < _partyChars.size(); ++i)
g_globals->_party.push_back(
g_globals->_roster[_partyChars[i]]);
+ g_globals->_currCharacter = &g_globals->_party.front();
// Load the given town
g_globals->_maps.loadTown(g_globals->_startingTown);
Commit: 262b93ec768fcbf7d97fa2190e7864063c9e786c
https://github.com/scummvm/scummvm/commit/262b93ec768fcbf7d97fa2190e7864063c9e786c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Don't clear monster list when starting combat
Changed paths:
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b66c872e8a7..4b4427c3b36 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -38,8 +38,6 @@ Combat::~Combat() {
}
void Combat::clear() {
- _monsterList.clear();
-
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
c._checked = false;
Commit: 13d94ffd94ca99906ff32981f568dd396aa8facc
https://github.com/scummvm/scummvm/commit/13d94ffd94ca99906ff32981f568dd396aa8facc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Simplify highlighting active combat char
Changed paths:
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index de050544f1a..0500759ad97 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -357,28 +357,9 @@ void Combat::writeAllOptions() {
writeString(0, 20, STRING["dialogs.combat.options_for"]);
writeString(0, 22, g_globals->_currCharacter->_name);
- switch (_currentChar) {
- case 0:
- writeChar(3, 3, (unsigned char)'\xB1');
- break;
- case 1:
- writeChar(7, 3, (unsigned char)'\xB2');
- break;
- case 2:
- writeChar(3, 4, (unsigned char)'\xB3');
- break;
- case 3:
- writeChar(7, 4, (unsigned char)'\xB4');
- break;
- case 4:
- writeChar(3, 5, (unsigned char)'\xB5');
- break;
- case 5:
- writeChar(7, 5, (unsigned char)'\xB6');
- break;
- default:
- break;
- }
+ // Highlight the currently active character
+ writeChar(3 + 4 * (_currentChar % 2), 3 + (_currentChar / 2),
+ (unsigned char)'1' + _currentChar + 0x80);
bool canAttack = _party[_currentChar]->_canAttack;
if (canAttack) {
Commit: 4b0ea19e74ee9a2d064e43d53474bd41f465ba88
https://github.com/scummvm/scummvm/commit/4b0ea19e74ee9a2d064e43d53474bd41f465ba88
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:49+01:00
Commit Message:
MM: MM1: Make separate monster list for combat vs encounter
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 4b4427c3b36..9cd6485126b 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -38,12 +38,14 @@ Combat::~Combat() {
}
void Combat::clear() {
+ // Reset party character combat flags
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
c._checked = false;
c._canAttack = false;
}
+ // Reset other fields
Common::fill(&_treasureFlags[0], &_treasureFlags[MAX_PARTY_SIZE], false);
_allowFight = _allowShoot = _allowCast = _allowAttack = false;
@@ -83,11 +85,13 @@ void Combat::clear() {
_party.push_back(&g_globals->_party[i]);
}
-void Combat::loadArrays() {
+void Combat::loadMonsters() {
Game::Encounter &enc = g_globals->_encounters;
+ // Set up hp and ac for the encounter monsters
for (uint i = 0; i < enc._monsterList.size(); ++i) {
Monster &mon = enc._monsterList[i];
+ _monsterP = &mon;
int val = getRandomNumber(8);
mon._defaultHP += val;
@@ -96,6 +100,10 @@ void Combat::loadArrays() {
monsterIndexOf();
}
+
+ // Now copy it into the active combat. This is kept as a
+ // separate list since defeated monsters are removed from it
+ _monsterList = g_globals->_encounters._monsterList;
}
void Combat::monsterIndexOf() {
@@ -251,10 +259,10 @@ void Combat::dispelParty() {
}
void Combat::combatLoop() {
- if (_monsterIndex != 0) {
- selectParty();
- } else {
+ if (_monsterList.empty()) {
defeatedMonsters();
+ } else {
+ selectParty();
}
}
@@ -281,10 +289,9 @@ void Combat::defeatedMonsters() {
_totalExperience = 0;
// Count total experience from all defeated monsters
- for (uint i = 0; i < _monsterList.size(); ++i) {
- _monsterP = &_monsterList[i];
- monsterIndexOf();
-
+ Common::Array<Monster> &monsters = g_globals->_encounters._monsterList;
+ for (uint i = 0; i < monsters.size(); ++i) {
+ _monsterP = &monsters[i];
_totalExperience += _monsterP->_experience;
setTreasure();
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3025efa6345..ba3a2dafbd5 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -105,7 +105,7 @@ protected:
*/
void clear();
- void loadArrays();
+ void loadMonsters();
/**
* Sets the _monsterIndex to the index of
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 46d3e91a550..c0867a85099 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -146,7 +146,7 @@ private:
void handlePartyEffects();
protected:
- Common::Array<Monster> &_monsterList;
+ Common::Array<Monster> _monsterList;
LineArray _lines;
int _damage = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 0500759ad97..e28b8ae8c8e 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -62,7 +62,7 @@ bool Combat::msgFocus(const FocusMessage &msg) {
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
- loadArrays();
+ loadMonsters();
setupCanAttacks();
setupHandicap();
Commit: 155041d578caaad51b4be949755c12764d9fbbad
https://github.com/scummvm/scummvm/commit/155041d578caaad51b4be949755c12764d9fbbad
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Differentiate remaining combat monsters list from original _monsterList
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 9cd6485126b..13a22826dc0 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -79,7 +79,7 @@ void Combat::clear() {
// TODO: clear everything
_roundNum = 1;
- _monstersCount = _monsterList.size();
+ _monstersCount = _remainingMonsters.size();
_party.clear();
for (uint i = 0; i < g_globals->_party.size(); ++i)
_party.push_back(&g_globals->_party[i]);
@@ -103,7 +103,7 @@ void Combat::loadMonsters() {
// Now copy it into the active combat. This is kept as a
// separate list since defeated monsters are removed from it
- _monsterList = g_globals->_encounters._monsterList;
+ _remainingMonsters = g_globals->_encounters._monsterList;
}
void Combat::monsterIndexOf() {
@@ -229,7 +229,7 @@ void Combat::setupHandicap() {
bool Combat::canMonsterCast() const {
return !(g_maps->_currentState & Maps::SFLAG_DISABLE_MONSTER_SPELLS) &&
- !(_monsterList[_monsterIndex]._status & (MONFLAG_BLIND | MONFLAG_SILENCED));
+ !(_remainingMonsters[_monsterIndex]._status & (MONFLAG_BLIND | MONFLAG_SILENCED));
}
void Combat::dispelParty() {
@@ -250,16 +250,16 @@ void Combat::dispelParty() {
g_globals->_currCharacter = tmpC;
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
- _monsterList[i]._status = 0;
+ _remainingMonsters[i]._status = 0;
}
_monsterP = tmpM;
}
void Combat::combatLoop() {
- if (_monsterList.empty()) {
+ if (_remainingMonsters.empty()) {
defeatedMonsters();
} else {
selectParty();
@@ -316,15 +316,15 @@ void Combat::defeatedMonsters() {
}
void Combat::loop1() {
- for (uint i = 0; i < _monsterList.size(); ++i) {
- _monsterP = &_monsterList[i];
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
+ _monsterP = &_remainingMonsters[i];
monsterIndexOf();
if (_monsterP->_speed && _monsterP->_speed >= _handicap3
- && !_monsterList[i]._checked) {
- _monsterList[i]._checked = true;
+ && !_remainingMonsters[i]._checked) {
+ _remainingMonsters[i]._checked = true;
- if (_monsterList[i]._status & (MONFLAG_ASLEEP | MONFLAG_HELD |
+ if (_remainingMonsters[i]._status & (MONFLAG_ASLEEP | MONFLAG_HELD |
MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
checkMonsterFlees();
return;
@@ -452,8 +452,8 @@ void Combat::clearArrays() {
for (uint i = 0; i < _party.size(); ++i)
_party[i]->_checked = false;
- for (uint i = 0; i < _monsterList.size(); ++i)
- _monsterList[i]._checked = false;
+ for (uint i = 0; i < _remainingMonsters.size(); ++i)
+ _remainingMonsters[i]._checked = false;
}
void Combat::updateHighestLevel() {
@@ -472,15 +472,15 @@ void Combat::updateHighestLevel() {
}
bool Combat::moveMonsters() {
- if (_attackerVal >= (int)_monsterList.size())
+ if (_attackerVal >= (int)_remainingMonsters.size())
return false;
bool hasAdvance = false;
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
_advanceIndex = i;
- if (!(_monsterList[i]._status & ~MONFLAG_SILENCED) &&
- _monsterList[i]._field1e & FIELD1E_80) {
+ if (!(_remainingMonsters[i]._status & ~MONFLAG_SILENCED) &&
+ _remainingMonsters[i]._field1e & FIELD1E_80) {
monsterAdvances();
hasAdvance = true;
}
@@ -493,9 +493,9 @@ void Combat::monsterAdvances() {
// TODO: I can't understand the advancement logic at all.
// So for now, I'm simply moving the monster forward one slot
assert(_advanceIndex > 0);
- Monster mon = _monsterList.remove_at(_advanceIndex);
- _monsterList.insert_at(_advanceIndex - 1, mon);
- _monsterP = &_monsterList[_advanceIndex - 1];
+ Monster mon = _remainingMonsters.remove_at(_advanceIndex);
+ _remainingMonsters.insert_at(_advanceIndex - 1, mon);
+ _monsterP = &_remainingMonsters[_advanceIndex - 1];
setMode(MONSTER_ADVANCES);
}
@@ -503,56 +503,56 @@ void Combat::monsterAdvances() {
bool Combat::monsterChanges() {
_monstersRegenerate = _monstersResistSpells = false;
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
if ((_monsterP->_field1e & FIELD1E_40) &&
- (_monsterP->_defaultHP != _monsterList[i]._hp)) {
+ (_monsterP->_defaultHP != _remainingMonsters[i]._hp)) {
_monstersRegenerate = true;
- int newVal = _monsterList[i]._hp + 5;
- _monsterList[i]._hp = (byte)newVal;
+ int newVal = _remainingMonsters[i]._hp + 5;
+ _remainingMonsters[i]._hp = (byte)newVal;
if (newVal >= 256 || newVal >= _monsterP->_defaultHP) {
- _monsterList[i]._hp = _monsterP->_defaultHP;
+ _remainingMonsters[i]._hp = _monsterP->_defaultHP;
}
}
- if (_monsterList[i]._status) {
+ if (_remainingMonsters[i]._status) {
proc2();
if (_val9) {
_monstersResistSpells = true;
- byte v = _monsterList[i]._status;
+ byte v = _remainingMonsters[i]._status;
v &= 0x7f;
- if (v != _monsterList[i]._status) {
- _monsterList[i]._status = v;
+ if (v != _remainingMonsters[i]._status) {
+ _remainingMonsters[i]._status = v;
} else {
v &= 0x3f;
- if (v != _monsterList[i]._status) {
- _monsterList[i]._status = v;
+ if (v != _remainingMonsters[i]._status) {
+ _remainingMonsters[i]._status = v;
} else {
v &= 0x1f;
- if (v != _monsterList[i]._status) {
- _monsterList[i]._status = v;
+ if (v != _remainingMonsters[i]._status) {
+ _remainingMonsters[i]._status = v;
} else {
v &= 0xf;
- if (v != _monsterList[i]._status) {
- _monsterList[i]._status = v;
+ if (v != _remainingMonsters[i]._status) {
+ _remainingMonsters[i]._status = v;
} else {
v &= 7;
- if (v != _monsterList[i]._status) {
- _monsterList[i]._status = v;
+ if (v != _remainingMonsters[i]._status) {
+ _remainingMonsters[i]._status = v;
} else {
v &= 3;
- if (v != _monsterList[i]._status) {
- _monsterList[i]._status = v;
+ if (v != _remainingMonsters[i]._status) {
+ _remainingMonsters[i]._status = v;
} else {
v &= 1;
- if (v != _monsterList[i]._status)
- _monsterList[i]._status = v;
+ if (v != _remainingMonsters[i]._status)
+ _remainingMonsters[i]._status = v;
else
- _monsterList[i]._status = 0;
+ _remainingMonsters[i]._status = 0;
}
}
}
@@ -609,8 +609,8 @@ void Combat::checkMonsterFlees() {
if (getRandomNumber(100) >= threshold) {
_monsterP->_experience = 0;
_monsterP->_field18 = 0;
- _monsterList[_monsterIndex]._hp = 0;
- _monsterList[_monsterIndex]._status = MONFLAG_DEAD;
+ _remainingMonsters[_monsterIndex]._hp = 0;
+ _remainingMonsters[_monsterIndex]._status = MONFLAG_DEAD;
removeMonster();
setMode(MONSTER_FLEES);
} else {
@@ -619,12 +619,12 @@ void Combat::checkMonsterFlees() {
}
bool Combat::checkMonsterSpells() {
- if (_monsterList.empty()) {
+ if (_remainingMonsters.empty()) {
setMode(DEFEATED_MONSTERS);
return true;
}
- if (_monsterList[_monsterIndex]._status & MONFLAG_MINDLESS) {
+ if (_remainingMonsters[_monsterIndex]._status & MONFLAG_MINDLESS) {
setMode(MONSTER_WANDERS);
return true;
}
@@ -638,7 +638,7 @@ bool Combat::checkMonsterSpells() {
if (!_monsterP->_specialAbility || _monsterP->_specialAbility >= 33)
return false;
- castMonsterSpell(_monsterList[_monsterIndex]._name,
+ castMonsterSpell(_remainingMonsters[_monsterIndex]._name,
_monsterP->_specialAbility);
setMode(MONSTER_SPELL);
return true;
@@ -690,10 +690,10 @@ void Combat::removeMonster() {
bool changed;
do {
changed = false;
- for (uint i = 0; i < _monsterList.size(); ++i) {
- _monsterP = &_monsterList[i];
- if (_monsterList[i]._status == MONFLAG_DEAD) {
- _monsterList.remove_at(i);
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
+ _monsterP = &_remainingMonsters[i];
+ if (_remainingMonsters[i]._status == MONFLAG_DEAD) {
+ _remainingMonsters.remove_at(i);
changed = true;
break;
}
@@ -828,7 +828,7 @@ void Combat::attackMonster(int monsterNum) {
_attackAttr2._current += (c._level + 1) / 2;
if (_attackAttr1._current || !(_monsterP->_field1a & FIELD1A_80)) {
- if (_monsterList[_monsterIndex]._status & (MONFLAG_ASLEEP |
+ if (_remainingMonsters[_monsterIndex]._status & (MONFLAG_ASLEEP |
MONFLAG_HELD | MONFLAG_WEBBED | MONFLAG_PARALYZED))
++_attackerLevel;
@@ -869,14 +869,14 @@ void Combat::addAttackDamage() {
}
void Combat::updateMonsterStatus() {
- int val = _monsterList[_monsterIndex]._hp - _damage;
+ int val = _remainingMonsters[_monsterIndex]._hp - _damage;
if (val <= 0) {
- _monsterList[_monsterIndex]._hp = 0;
- _monsterList[_monsterIndex]._status = MONFLAG_DEAD;
+ _remainingMonsters[_monsterIndex]._hp = 0;
+ _remainingMonsters[_monsterIndex]._status = MONFLAG_DEAD;
warning("TODO: message that monster goes down");
} else {
- _monsterList[_monsterIndex]._hp = val;
- _monsterList[_monsterIndex]._status &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
+ _remainingMonsters[_monsterIndex]._hp = val;
+ _remainingMonsters[_monsterIndex]._status &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
}
}
@@ -897,7 +897,7 @@ bool Combat::monsterTouch(Common::String &line) {
}
void Combat::iterateMonsters1() {
- _spellMonsterCount = _monsterList.size();
+ _spellMonsterCount = _remainingMonsters.size();
iterateMonsters1Inner();
}
@@ -931,7 +931,7 @@ void Combat::iterateMonsters1Inner() {
effect = STRING["monster_spells.not_affected"];
} else {
- _monsterList[getMonsterIndex()]._status |=
+ _remainingMonsters[getMonsterIndex()]._status |=
g_globals->_spellsState._newCondition;
byte bits = g_globals->_spellsState._newCondition;
@@ -960,7 +960,7 @@ void Combat::iterateMonsters1Inner() {
isEnd = true;
}
if (!isEnd)
- isEnd = ((int)_monsterList.size() + _destMonsterNum - _spellMonsterCount) < 0;
+ isEnd = ((int)_remainingMonsters.size() + _destMonsterNum - _spellMonsterCount) < 0;
if (!isEnd) {
// Move to next iteration after display timeout
@@ -973,7 +973,7 @@ void Combat::iterateMonsters1Inner() {
}
void Combat::iterateMonsters2() {
- _spellMonsterCount = _monsterList.size();
+ _spellMonsterCount = _remainingMonsters.size();
iterateMonsters2Inner();
}
@@ -1029,7 +1029,7 @@ void Combat::iterateMonsters2Inner() {
msg._lines.push_back(Line(0, 1, line2));
- if (_damage >= _monsterList[getMonsterIndex()]._hp) {
+ if (_damage >= _remainingMonsters[getMonsterIndex()]._hp) {
msg._lines.push_back(Line(0, 2, STRING["monster_spells.and_goes_down"]));
}
}
@@ -1043,7 +1043,7 @@ void Combat::iterateMonsters2Inner() {
isEnd = true;
}
if (!isEnd)
- isEnd = ((int)_monsterList.size() + _destMonsterNum - _spellMonsterCount) < 0;
+ isEnd = ((int)_remainingMonsters.size() + _destMonsterNum - _spellMonsterCount) < 0;
if (!isEnd) {
// Move to next iteration after display timeout
@@ -1066,7 +1066,7 @@ void Combat::characterDone() {
void Combat::resetDestMonster() {
_destMonsterNum = 0;
- _monsterP = &_monsterList[0];
+ _monsterP = &_remainingMonsters[0];
monsterIndexOf();
g_globals->_spellsState._resistanceType = RESISTANCE_15;
}
@@ -1094,13 +1094,13 @@ void Combat::turnUndead() {
} else {
_turnUndeadUsed = true;
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
Monster *monster = _monsterP;
if ((monster->_resistUndead & IS_UNDEAD) &&
(getRandomNumber(20) + g_globals->_currCharacter->_level) >=
- (_monsterList[i]._hp * 2 + 10)) {
+ (_remainingMonsters[i]._hp * 2 + 10)) {
destroyMonster();
++_monstersDestroyedCtr;
}
@@ -1116,7 +1116,7 @@ void Combat::turnUndead() {
}
void Combat::destroyMonster() {
- _monsterList[getMonsterIndex()]._status = MONFLAG_DEAD;
+ _remainingMonsters[getMonsterIndex()]._status = MONFLAG_DEAD;
Sound::sound2(SOUND_9);
}
@@ -1212,7 +1212,7 @@ bool Combat::divineIntervention() {
void Combat::holyWord() {
_monstersDestroyedCtr = 0;
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
if (_monsterP->_resistUndead & IS_UNDEAD) {
destroyMonster();
@@ -1232,15 +1232,15 @@ void Combat::identifyMonster() {
InfoMessage msg;
Common::String line;
- line = _monsterList[_destMonsterNum]._name;
+ line = _remainingMonsters[_destMonsterNum]._name;
line += ':';
while (line.size() < COL2)
line += ' ';
line += STRING["spells.info.hp"];
- line += Common::String::format("%d", _monsterList[_destMonsterNum]._hp);
+ line += Common::String::format("%d", _remainingMonsters[_destMonsterNum]._hp);
line += " ";
line += STRING["spells.info.ac"];
- line += Common::String::format("%d", _monsterList[_destMonsterNum]._ac);
+ line += Common::String::format("%d", _remainingMonsters[_destMonsterNum]._ac);
msg._lines.push_back(Line(0, 0, line));
line = STRING["spells.info.speed"];
@@ -1317,7 +1317,7 @@ void Combat::makeRoom() {
}
void Combat::slow() {
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
_monsterP->_speed = MAX(_monsterP->_speed / 2, 1);
}
@@ -1326,9 +1326,9 @@ void Combat::slow() {
void Combat::weaken() {
SpellsState &ss = g_globals->_spellsState;
- for (uint i = 0; i < _monsterList.size(); ++i) {
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
- _monsterList[i]._ac = MAX((int)_monsterList[i]._ac - 1, 1);
+ _remainingMonsters[i]._ac = MAX((int)_remainingMonsters[i]._ac - 1, 1);
}
resetDestMonster();
@@ -1353,7 +1353,7 @@ bool Combat::web() {
bool Combat::acidRain() {
SpellsState &ss = g_globals->_spellsState;
- if (_attackerVal >= (int)_monsterList.size())
+ if (_attackerVal >= (int)_remainingMonsters.size())
return false;
_destMonsterNum = _attackerVal;
@@ -1434,7 +1434,7 @@ void Combat::disintegration() {
}
void Combat::monsterAttackRandom() {
- size_t monsterNameSize = _monsterList[getMonsterIndex()]._name.size() + 1;
+ size_t monsterNameSize = _remainingMonsters[getMonsterIndex()]._name.size() + 1;
_monsterAttackStyle = getRandomNumber((monsterNameSize < 13) ? 15 : 11);
_val10 = 0;
@@ -1455,7 +1455,7 @@ void Combat::monsterAttackInner() {
_destAC = c._ac._base;
int monsterIndex = getMonsterIndex();
- _attackerLevel = _monsterList[monsterIndex]._level * 2 + 4;
+ _attackerLevel = _remainingMonsters[monsterIndex]._level * 2 + 4;
if (c._condition & (ASLEEP | BLINDED | PARALYZED))
_attackerLevel += 5;
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 74b67d22b57..87dcd1ee0ec 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -63,7 +63,7 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
&SpellsMonsters::spell32_swarm
};
-SpellsMonsters::SpellsMonsters() : _monsterList(g_globals->_encounters._monsterList) {
+SpellsMonsters::SpellsMonsters() : _remainingMonsters(g_globals->_encounters._monsterList) {
}
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
@@ -103,7 +103,7 @@ void SpellsMonsters::spell03_fire() {
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
- int count = _monsterList[getMonsterIndex()]._level;
+ int count = _remainingMonsters[getMonsterIndex()]._level;
g_globals->_spellsState._newCondition += count * 6;
damageRandomChar();
@@ -157,7 +157,7 @@ void SpellsMonsters::spell08_paralyze() {
g_globals->_spellsState._resistanceType = RESISTANCE_FEAR;
g_globals->_spellsState._newCondition = PARALYZED;
- if (_monsterList[getMonsterIndex()]._level >= 5) {
+ if (_remainingMonsters[getMonsterIndex()]._level >= 5) {
handlePartyEffects();
} else {
chooseCharacter();
@@ -200,9 +200,9 @@ void SpellsMonsters::spell12_explode() {
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
g_globals->_spellsState._newCondition = getRandomNumber(
- _monsterList[getMonsterIndex()]._level);
- _monsterList[getMonsterIndex()]._level = 0;
- _monsterList[getMonsterIndex()]._status = MONFLAG_DEAD;
+ _remainingMonsters[getMonsterIndex()]._level);
+ _remainingMonsters[getMonsterIndex()]._level = 0;
+ _remainingMonsters[getMonsterIndex()]._status = MONFLAG_DEAD;
removeMonster();
add(':');
@@ -218,7 +218,7 @@ void SpellsMonsters::spell13_fireball() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 6 *
- _monsterList[getMonsterIndex()]._level;
+ _remainingMonsters[getMonsterIndex()]._level;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition) + 4;
add(':');
@@ -235,7 +235,7 @@ void SpellsMonsters::spell14_fireBreath() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 8 *
- _monsterList[getMonsterIndex()]._level;
+ _remainingMonsters[getMonsterIndex()]._level;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition);
add(':');
@@ -350,7 +350,7 @@ void SpellsMonsters::spell25_poison() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.poison"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
- g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -362,7 +362,7 @@ void SpellsMonsters::spell26_lightning() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.lightning"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
- g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -374,7 +374,7 @@ void SpellsMonsters::spell27_frost() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.frost"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_COLD;
- g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -386,7 +386,7 @@ void SpellsMonsters::spell28_spikes() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.spikes"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
- g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -398,7 +398,7 @@ void SpellsMonsters::spell29_acid() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.acid"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ACID;
- g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -410,7 +410,7 @@ void SpellsMonsters::spell30_fire() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.fire"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
- g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -419,7 +419,7 @@ void SpellsMonsters::spell30_fire() {
void SpellsMonsters::spell31_energy() {
add(STRING["monster_spellsState.energy"]);
- g_globals->_spellsState._newCondition = _monsterList[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
++g_globals->_spellsState._mmVal2;
add(':');
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index c0867a85099..571d378abd2 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -146,7 +146,7 @@ private:
void handlePartyEffects();
protected:
- Common::Array<Monster> _monsterList;
+ Common::Array<Monster> _remainingMonsters;
LineArray _lines;
int _damage = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index e28b8ae8c8e..945a9f47747 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -402,7 +402,7 @@ void Combat::writeExchangeSelect() {
}
void Combat::writeFightSelect() {
- _fightCount = MIN(_attackerVal, (int)_monsterList.size());
+ _fightCount = MIN(_attackerVal, (int)_remainingMonsters.size());
writeString(10, 0, Common::String::format(
STRING["dialogs.combat.fight_which"].c_str(), '@' + _fightCount));
@@ -410,7 +410,7 @@ void Combat::writeFightSelect() {
}
void Combat::writeShootSelect() {
- _fightCount = MIN(_attackerVal, (int)_monsterList.size());
+ _fightCount = MIN(_attackerVal, (int)_remainingMonsters.size());
writeString(10, 0, Common::String::format(
STRING["dialogs.combat.shoot_which"].c_str(), '@' + _fightCount));
@@ -482,11 +482,11 @@ void Combat::writePartyNumbers() {
}
void Combat::writeMonsters() {
- if (_monsterList.empty()) {
+ if (_remainingMonsters.empty()) {
_textPos = Common::Point(10, 0);
writeSpaces(30);
} else {
- for (int i = 0; i < (int)_monsterList.size(); ++i) {
+ for (int i = 0; i < (int)_remainingMonsters.size(); ++i) {
_textPos = Common::Point(11, i);
writeChar(i < _attackerVal ? '+' : ' ');
unsigned char c = 'A' + i;
@@ -496,7 +496,7 @@ void Combat::writeMonsters() {
writeChar(c);
writeString(") ");
- writeString(_monsterList[i]._name);
+ writeString(_remainingMonsters[i]._name);
writeMonsterStatus(i);
}
}
@@ -509,7 +509,7 @@ void Combat::writeMonsters() {
void Combat::writeMonsterStatus(int monsterNum) {
monsterSetPtr(monsterNum);
- byte statusBits = _monsterList[monsterNum]._status;
+ byte statusBits = _remainingMonsters[monsterNum]._status;
if (statusBits) {
writeDots();
@@ -525,7 +525,7 @@ void Combat::writeMonsterStatus(int monsterNum) {
writeString(STRING[Common::String::format("dialogs.combat.status.%d",
status)]);
- } else if (_monsterList[monsterNum]._hp != _monsterP->_defaultHP) {
+ } else if (_remainingMonsters[monsterNum]._hp != _monsterP->_defaultHP) {
writeDots();
writeString(STRING["dialogs.combat.status.wounded"]);
} else {
@@ -715,7 +715,7 @@ void Combat::exchange() {
void Combat::fight() {
if (_allowFight) {
- if (_monsterList.size() < 2) {
+ if (_remainingMonsters.size() < 2) {
attackMonsterPhysical();
} else {
setOption(OPTION_FIGHT);
@@ -725,7 +725,7 @@ void Combat::fight() {
void Combat::shoot() {
if (_allowShoot) {
- if (_monsterList.size() < 2) {
+ if (_remainingMonsters.size() < 2) {
attackMonsterPhysical();
} else {
setOption(OPTION_SHOOT);
Commit: 91c997352acb7d39cdebed5258ed94fbfca35daf
https://github.com/scummvm/scummvm/commit/91c997352acb7d39cdebed5258ed94fbfca35daf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Cleanup of post-combat treasure setup
Changed paths:
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 13a22826dc0..d6fcebae3e2 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -275,7 +275,7 @@ void Combat::selectParty() {
if (speed && speed >= _handicap2) {
if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
// Character is enabled
- _mode = SELECT_OPTION;
+ setMode(SELECT_OPTION);
return;
}
}
@@ -347,6 +347,7 @@ void Combat::setTreasure() {
_val6 = MAX(_val6, _val7);
if (_val7 & 1)
+ // Add gems
g_globals->_treasure[8] += getRandomNumber(6);
if (_val7 & 6) {
@@ -373,22 +374,22 @@ void Combat::selectTreasure() {
#undef SHIFT_BIT
auto &treasure = g_globals->_treasure;
- treasure[1] = 0;
+ treasure._trapType = 0;
if (_treasureFlags[4]) {
- treasure[2] = 10;
+ treasure._container = 10;
} else if (_treasureFlags[3]) {
- treasure[2] = 5 + getRandomNumber(4);
+ treasure._container = 5 + getRandomNumber(4);
} else if (_treasureFlags[2]) {
- treasure[2] = 4 + getRandomNumber(4);
+ treasure._container = 4 + getRandomNumber(4);
} else if (_treasureFlags[1]) {
- treasure[2] = 3 + getRandomNumber(4);
+ treasure._container = 3 + getRandomNumber(4);
} else if (_treasureFlags[0] || treasure[8]) {
- treasure[2] = 1 + getRandomNumber(4);
+ treasure._container = 1 + getRandomNumber(4);
} else if (treasure[7]) {
- treasure[2] = getRandomNumber(4) - 1;
+ treasure._container = getRandomNumber(4) - 1;
} else {
- treasure[2] = getRandomNumber(2) - 1;
+ treasure._container = getRandomNumber(2) - 1;
}
}
Commit: 770502487b29a573216178d71375bf6c09cb2265
https://github.com/scummvm/scummvm/commit/770502487b29a573216178d71375bf6c09cb2265
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Change _remainingMonsters to be a Monster * array
This is needed, because pointers to monsters need to be
resolved to monster records in the encounter list, and
just making copies, the correct monster wasn't being found
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/spells_monsters.cpp
engines/mm/mm1/game/spells_monsters.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index d6fcebae3e2..53c0332db0e 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -103,7 +103,9 @@ void Combat::loadMonsters() {
// Now copy it into the active combat. This is kept as a
// separate list since defeated monsters are removed from it
- _remainingMonsters = g_globals->_encounters._monsterList;
+ _remainingMonsters.clear();
+ for (uint i = 0; i < enc._monsterList.size(); ++i)
+ _remainingMonsters.push_back(&enc._monsterList[i]);
}
void Combat::monsterIndexOf() {
@@ -229,7 +231,8 @@ void Combat::setupHandicap() {
bool Combat::canMonsterCast() const {
return !(g_maps->_currentState & Maps::SFLAG_DISABLE_MONSTER_SPELLS) &&
- !(_remainingMonsters[_monsterIndex]._status & (MONFLAG_BLIND | MONFLAG_SILENCED));
+ !(g_globals->_encounters._monsterList[_monsterIndex]._status
+ & (MONFLAG_BLIND | MONFLAG_SILENCED));
}
void Combat::dispelParty() {
@@ -252,7 +255,7 @@ void Combat::dispelParty() {
for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
- _remainingMonsters[i]._status = 0;
+ _remainingMonsters[i]->_status = 0;
}
_monsterP = tmpM;
@@ -281,6 +284,7 @@ void Combat::selectParty() {
}
}
+ // At this point, a monster has precedence to attack
loop1();
}
@@ -317,14 +321,14 @@ void Combat::defeatedMonsters() {
void Combat::loop1() {
for (uint i = 0; i < _remainingMonsters.size(); ++i) {
- _monsterP = &_remainingMonsters[i];
+ _monsterP = _remainingMonsters[i];
monsterIndexOf();
if (_monsterP->_speed && _monsterP->_speed >= _handicap3
- && !_remainingMonsters[i]._checked) {
- _remainingMonsters[i]._checked = true;
+ && !_remainingMonsters[i]->_checked) {
+ _remainingMonsters[i]->_checked = true;
- if (_remainingMonsters[i]._status & (MONFLAG_ASLEEP | MONFLAG_HELD |
+ if (_remainingMonsters[i]->_status & (MONFLAG_ASLEEP | MONFLAG_HELD |
MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
checkMonsterFlees();
return;
@@ -454,7 +458,7 @@ void Combat::clearArrays() {
_party[i]->_checked = false;
for (uint i = 0; i < _remainingMonsters.size(); ++i)
- _remainingMonsters[i]._checked = false;
+ _remainingMonsters[i]->_checked = false;
}
void Combat::updateHighestLevel() {
@@ -480,8 +484,8 @@ bool Combat::moveMonsters() {
for (uint i = 0; i < _remainingMonsters.size(); ++i) {
_advanceIndex = i;
- if (!(_remainingMonsters[i]._status & ~MONFLAG_SILENCED) &&
- _remainingMonsters[i]._field1e & FIELD1E_80) {
+ if (!(_remainingMonsters[i]->_status & ~MONFLAG_SILENCED) &&
+ _remainingMonsters[i]->_field1e & FIELD1E_80) {
monsterAdvances();
hasAdvance = true;
}
@@ -494,9 +498,9 @@ void Combat::monsterAdvances() {
// TODO: I can't understand the advancement logic at all.
// So for now, I'm simply moving the monster forward one slot
assert(_advanceIndex > 0);
- Monster mon = _remainingMonsters.remove_at(_advanceIndex);
+ Monster *mon = _remainingMonsters.remove_at(_advanceIndex);
_remainingMonsters.insert_at(_advanceIndex - 1, mon);
- _monsterP = &_remainingMonsters[_advanceIndex - 1];
+ _monsterP = _remainingMonsters[_advanceIndex - 1];
setMode(MONSTER_ADVANCES);
}
@@ -508,59 +512,58 @@ bool Combat::monsterChanges() {
monsterSetPtr(i);
if ((_monsterP->_field1e & FIELD1E_40) &&
- (_monsterP->_defaultHP != _remainingMonsters[i]._hp)) {
+ (_monsterP->_defaultHP != _remainingMonsters[i]->_hp)) {
_monstersRegenerate = true;
- int newVal = _remainingMonsters[i]._hp + 5;
- _remainingMonsters[i]._hp = (byte)newVal;
+ int newVal = _remainingMonsters[i]->_hp + 5;
+ _remainingMonsters[i]->_hp = (byte)newVal;
if (newVal >= 256 || newVal >= _monsterP->_defaultHP) {
- _remainingMonsters[i]._hp = _monsterP->_defaultHP;
+ _remainingMonsters[i]->_hp = _monsterP->_defaultHP;
}
}
- if (_remainingMonsters[i]._status) {
+ if (_remainingMonsters[i]->_status) {
proc2();
if (_val9) {
_monstersResistSpells = true;
- byte v = _remainingMonsters[i]._status;
+ byte v = _remainingMonsters[i]->_status;
v &= 0x7f;
- if (v != _remainingMonsters[i]._status) {
- _remainingMonsters[i]._status = v;
+ if (v != _remainingMonsters[i]->_status) {
+ _remainingMonsters[i]->_status = v;
} else {
v &= 0x3f;
- if (v != _remainingMonsters[i]._status) {
- _remainingMonsters[i]._status = v;
+ if (v != _remainingMonsters[i]->_status) {
+ _remainingMonsters[i]->_status = v;
} else {
v &= 0x1f;
- if (v != _remainingMonsters[i]._status) {
- _remainingMonsters[i]._status = v;
+ if (v != _remainingMonsters[i]->_status) {
+ _remainingMonsters[i]->_status = v;
} else {
v &= 0xf;
- if (v != _remainingMonsters[i]._status) {
- _remainingMonsters[i]._status = v;
+ if (v != _remainingMonsters[i]->_status) {
+ _remainingMonsters[i]->_status = v;
} else {
v &= 7;
- if (v != _remainingMonsters[i]._status) {
- _remainingMonsters[i]._status = v;
+ if (v != _remainingMonsters[i]->_status) {
+ _remainingMonsters[i]->_status = v;
} else {
v &= 3;
- if (v != _remainingMonsters[i]._status) {
- _remainingMonsters[i]._status = v;
+ if (v != _remainingMonsters[i]->_status) {
+ _remainingMonsters[i]->_status = v;
} else {
v &= 1;
- if (v != _remainingMonsters[i]._status)
- _remainingMonsters[i]._status = v;
+ if (v != _remainingMonsters[i]->_status)
+ _remainingMonsters[i]->_status = v;
else
- _remainingMonsters[i]._status = 0;
+ _remainingMonsters[i]->_status = 0;
}
}
}
}
}
}
-
}
}
}
@@ -576,7 +579,7 @@ void Combat::proc2() {
}
void Combat::checkMonsterFlees() {
- const Encounter &enc = g_globals->_encounters;
+ Encounter &enc = g_globals->_encounters;
byte bitset = _monsterP->_field1e;
int threshold = -1;
@@ -610,8 +613,8 @@ void Combat::checkMonsterFlees() {
if (getRandomNumber(100) >= threshold) {
_monsterP->_experience = 0;
_monsterP->_field18 = 0;
- _remainingMonsters[_monsterIndex]._hp = 0;
- _remainingMonsters[_monsterIndex]._status = MONFLAG_DEAD;
+ enc._monsterList[_monsterIndex]._hp = 0;
+ enc._monsterList[_monsterIndex]._status = MONFLAG_DEAD;
removeMonster();
setMode(MONSTER_FLEES);
} else {
@@ -620,12 +623,13 @@ void Combat::checkMonsterFlees() {
}
bool Combat::checkMonsterSpells() {
+ Encounter &enc = g_globals->_encounters;
if (_remainingMonsters.empty()) {
setMode(DEFEATED_MONSTERS);
return true;
}
- if (_remainingMonsters[_monsterIndex]._status & MONFLAG_MINDLESS) {
+ if (enc._monsterList[_monsterIndex]._status & MONFLAG_MINDLESS) {
setMode(MONSTER_WANDERS);
return true;
}
@@ -639,7 +643,7 @@ bool Combat::checkMonsterSpells() {
if (!_monsterP->_specialAbility || _monsterP->_specialAbility >= 33)
return false;
- castMonsterSpell(_remainingMonsters[_monsterIndex]._name,
+ castMonsterSpell(enc._monsterList[_monsterIndex]._name,
_monsterP->_specialAbility);
setMode(MONSTER_SPELL);
return true;
@@ -692,8 +696,8 @@ void Combat::removeMonster() {
do {
changed = false;
for (uint i = 0; i < _remainingMonsters.size(); ++i) {
- _monsterP = &_remainingMonsters[i];
- if (_remainingMonsters[i]._status == MONFLAG_DEAD) {
+ _monsterP = _remainingMonsters[i];
+ if (_remainingMonsters[i]->_status == MONFLAG_DEAD) {
_remainingMonsters.remove_at(i);
changed = true;
break;
@@ -743,6 +747,7 @@ void Combat::attackMonsterShooting() {
}
void Combat::attackMonster(int monsterNum) {
+ Encounter &enc = g_globals->_encounters;
_activeMonsterNum = monsterNum;
monsterSetPtr(monsterNum);
@@ -829,7 +834,7 @@ void Combat::attackMonster(int monsterNum) {
_attackAttr2._current += (c._level + 1) / 2;
if (_attackAttr1._current || !(_monsterP->_field1a & FIELD1A_80)) {
- if (_remainingMonsters[_monsterIndex]._status & (MONFLAG_ASLEEP |
+ if (enc._monsterList[_monsterIndex]._status & (MONFLAG_ASLEEP |
MONFLAG_HELD | MONFLAG_WEBBED | MONFLAG_PARALYZED))
++_attackerLevel;
@@ -870,14 +875,15 @@ void Combat::addAttackDamage() {
}
void Combat::updateMonsterStatus() {
- int val = _remainingMonsters[_monsterIndex]._hp - _damage;
+ Encounter &enc = g_globals->_encounters;
+ int val = enc._monsterList[_monsterIndex]._hp - _damage;
if (val <= 0) {
- _remainingMonsters[_monsterIndex]._hp = 0;
- _remainingMonsters[_monsterIndex]._status = MONFLAG_DEAD;
+ enc._monsterList[_monsterIndex]._hp = 0;
+ enc._monsterList[_monsterIndex]._status = MONFLAG_DEAD;
warning("TODO: message that monster goes down");
} else {
- _remainingMonsters[_monsterIndex]._hp = val;
- _remainingMonsters[_monsterIndex]._status &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
+ enc._monsterList[_monsterIndex]._hp = val;
+ enc._monsterList[_monsterIndex]._status &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
}
}
@@ -903,6 +909,7 @@ void Combat::iterateMonsters1() {
}
void Combat::iterateMonsters1Inner() {
+ Encounter &enc = g_globals->_encounters;
Common::String line1 = Common::String::format("|%s| %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
@@ -932,7 +939,7 @@ void Combat::iterateMonsters1Inner() {
effect = STRING["monster_spells.not_affected"];
} else {
- _remainingMonsters[getMonsterIndex()]._status |=
+ enc._monsterList[getMonsterIndex()]._status |=
g_globals->_spellsState._newCondition;
byte bits = g_globals->_spellsState._newCondition;
@@ -979,6 +986,7 @@ void Combat::iterateMonsters2() {
}
void Combat::iterateMonsters2Inner() {
+ Encounter &enc = g_globals->_encounters;
Common::String line1 = Common::String::format("|%s| %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
@@ -1030,7 +1038,7 @@ void Combat::iterateMonsters2Inner() {
msg._lines.push_back(Line(0, 1, line2));
- if (_damage >= _remainingMonsters[getMonsterIndex()]._hp) {
+ if (_damage >= enc._monsterList[getMonsterIndex()]._hp) {
msg._lines.push_back(Line(0, 2, STRING["monster_spells.and_goes_down"]));
}
}
@@ -1067,7 +1075,7 @@ void Combat::characterDone() {
void Combat::resetDestMonster() {
_destMonsterNum = 0;
- _monsterP = &_remainingMonsters[0];
+ _monsterP = _remainingMonsters[0];
monsterIndexOf();
g_globals->_spellsState._resistanceType = RESISTANCE_15;
}
@@ -1101,7 +1109,7 @@ void Combat::turnUndead() {
if ((monster->_resistUndead & IS_UNDEAD) &&
(getRandomNumber(20) + g_globals->_currCharacter->_level) >=
- (_remainingMonsters[i]._hp * 2 + 10)) {
+ (_remainingMonsters[i]->_hp * 2 + 10)) {
destroyMonster();
++_monstersDestroyedCtr;
}
@@ -1117,7 +1125,8 @@ void Combat::turnUndead() {
}
void Combat::destroyMonster() {
- _remainingMonsters[getMonsterIndex()]._status = MONFLAG_DEAD;
+ Encounter &enc = g_globals->_encounters;
+ enc._monsterList[getMonsterIndex()]._status = MONFLAG_DEAD;
Sound::sound2(SOUND_9);
}
@@ -1232,16 +1241,17 @@ void Combat::holyWord() {
void Combat::identifyMonster() {
InfoMessage msg;
Common::String line;
+ assert(_monsterP == _remainingMonsters[_destMonsterNum]);
- line = _remainingMonsters[_destMonsterNum]._name;
+ line = _monsterP->_name;
line += ':';
while (line.size() < COL2)
line += ' ';
line += STRING["spells.info.hp"];
- line += Common::String::format("%d", _remainingMonsters[_destMonsterNum]._hp);
+ line += Common::String::format("%d", _monsterP->_hp);
line += " ";
line += STRING["spells.info.ac"];
- line += Common::String::format("%d", _remainingMonsters[_destMonsterNum]._ac);
+ line += Common::String::format("%d", _monsterP->_ac);
msg._lines.push_back(Line(0, 0, line));
line = STRING["spells.info.speed"];
@@ -1329,7 +1339,7 @@ void Combat::weaken() {
for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
- _remainingMonsters[i]._ac = MAX((int)_remainingMonsters[i]._ac - 1, 1);
+ _remainingMonsters[i]->_ac = MAX((int)_remainingMonsters[i]->_ac - 1, 1);
}
resetDestMonster();
@@ -1435,7 +1445,8 @@ void Combat::disintegration() {
}
void Combat::monsterAttackRandom() {
- size_t monsterNameSize = _remainingMonsters[getMonsterIndex()]._name.size() + 1;
+ Encounter &enc = g_globals->_encounters;
+ size_t monsterNameSize = enc._monsterList[getMonsterIndex()]._name.size() + 1;
_monsterAttackStyle = getRandomNumber((monsterNameSize < 13) ? 15 : 11);
_val10 = 0;
@@ -1452,11 +1463,12 @@ void Combat::monsterAttackShooting() {
void Combat::monsterAttackInner() {
+ Encounter &enc = g_globals->_encounters;
Character &c = *g_globals->_currCharacter;
_destAC = c._ac._base;
int monsterIndex = getMonsterIndex();
- _attackerLevel = _remainingMonsters[monsterIndex]._level * 2 + 4;
+ _attackerLevel = enc._monsterList[monsterIndex]._level * 2 + 4;
if (c._condition & (ASLEEP | BLINDED | PARALYZED))
_attackerLevel += 5;
diff --git a/engines/mm/mm1/game/spells_monsters.cpp b/engines/mm/mm1/game/spells_monsters.cpp
index 87dcd1ee0ec..63330326988 100644
--- a/engines/mm/mm1/game/spells_monsters.cpp
+++ b/engines/mm/mm1/game/spells_monsters.cpp
@@ -63,7 +63,7 @@ const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
&SpellsMonsters::spell32_swarm
};
-SpellsMonsters::SpellsMonsters() : _remainingMonsters(g_globals->_encounters._monsterList) {
+SpellsMonsters::SpellsMonsters() {
}
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
@@ -103,7 +103,7 @@ void SpellsMonsters::spell03_fire() {
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
- int count = _remainingMonsters[getMonsterIndex()]._level;
+ int count = _remainingMonsters[getMonsterIndex()]->_level;
g_globals->_spellsState._newCondition += count * 6;
damageRandomChar();
@@ -157,7 +157,7 @@ void SpellsMonsters::spell08_paralyze() {
g_globals->_spellsState._resistanceType = RESISTANCE_FEAR;
g_globals->_spellsState._newCondition = PARALYZED;
- if (_remainingMonsters[getMonsterIndex()]._level >= 5) {
+ if (_remainingMonsters[getMonsterIndex()]->_level >= 5) {
handlePartyEffects();
} else {
chooseCharacter();
@@ -200,9 +200,9 @@ void SpellsMonsters::spell12_explode() {
++g_globals->_spellsState._mmVal2;
g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
g_globals->_spellsState._newCondition = getRandomNumber(
- _remainingMonsters[getMonsterIndex()]._level);
- _remainingMonsters[getMonsterIndex()]._level = 0;
- _remainingMonsters[getMonsterIndex()]._status = MONFLAG_DEAD;
+ _remainingMonsters[getMonsterIndex()]->_level);
+ _remainingMonsters[getMonsterIndex()]->_level = 0;
+ _remainingMonsters[getMonsterIndex()]->_status = MONFLAG_DEAD;
removeMonster();
add(':');
@@ -218,7 +218,7 @@ void SpellsMonsters::spell13_fireball() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 6 *
- _remainingMonsters[getMonsterIndex()]._level;
+ _remainingMonsters[getMonsterIndex()]->_level;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition) + 4;
add(':');
@@ -235,7 +235,7 @@ void SpellsMonsters::spell14_fireBreath() {
// This whole condition choice makes no sense
g_globals->_spellsState._newCondition += 8 *
- _remainingMonsters[getMonsterIndex()]._level;
+ _remainingMonsters[getMonsterIndex()]->_level;
g_globals->_spellsState._newCondition = getRandomNumber(g_globals->_spellsState._newCondition);
add(':');
@@ -350,7 +350,7 @@ void SpellsMonsters::spell25_poison() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.poison"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_POISON;
- g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]->_hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -362,7 +362,7 @@ void SpellsMonsters::spell26_lightning() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.lightning"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
- g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]->_hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -374,7 +374,7 @@ void SpellsMonsters::spell27_frost() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.frost"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_COLD;
- g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]->_hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -386,7 +386,7 @@ void SpellsMonsters::spell28_spikes() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.spikes"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ELECTRICITY;
- g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]->_hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -398,7 +398,7 @@ void SpellsMonsters::spell29_acid() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.acid"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_ACID;
- g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]->_hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -410,7 +410,7 @@ void SpellsMonsters::spell30_fire() {
STRING["monster_spellsState.breathes"].c_str(),
STRING["monster_spellsState.fire"].c_str()));
g_globals->_spellsState._resistanceType = RESISTANCE_FIRE;
- g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]->_hp;
++g_globals->_spellsState._mmVal2;
add(':');
@@ -419,7 +419,7 @@ void SpellsMonsters::spell30_fire() {
void SpellsMonsters::spell31_energy() {
add(STRING["monster_spellsState.energy"]);
- g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]._hp;
+ g_globals->_spellsState._newCondition = _remainingMonsters[getMonsterIndex()]->_hp;
++g_globals->_spellsState._mmVal2;
add(':');
diff --git a/engines/mm/mm1/game/spells_monsters.h b/engines/mm/mm1/game/spells_monsters.h
index 571d378abd2..451669c91f4 100644
--- a/engines/mm/mm1/game/spells_monsters.h
+++ b/engines/mm/mm1/game/spells_monsters.h
@@ -146,7 +146,7 @@ private:
void handlePartyEffects();
protected:
- Common::Array<Monster> _remainingMonsters;
+ Common::Array<Monster *> _remainingMonsters;
LineArray _lines;
int _damage = 0;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 945a9f47747..23dbc9907b3 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -496,7 +496,7 @@ void Combat::writeMonsters() {
writeChar(c);
writeString(") ");
- writeString(_remainingMonsters[i]._name);
+ writeString(_remainingMonsters[i]->_name);
writeMonsterStatus(i);
}
}
@@ -509,7 +509,7 @@ void Combat::writeMonsters() {
void Combat::writeMonsterStatus(int monsterNum) {
monsterSetPtr(monsterNum);
- byte statusBits = _remainingMonsters[monsterNum]._status;
+ byte statusBits = _remainingMonsters[monsterNum]->_status;
if (statusBits) {
writeDots();
@@ -525,7 +525,7 @@ void Combat::writeMonsterStatus(int monsterNum) {
writeString(STRING[Common::String::format("dialogs.combat.status.%d",
status)]);
- } else if (_remainingMonsters[monsterNum]._hp != _monsterP->_defaultHP) {
+ } else if (_remainingMonsters[monsterNum]->_hp != _monsterP->_defaultHP) {
writeDots();
writeString(STRING["dialogs.combat.status.wounded"]);
} else {
Commit: 830ef7f1f270874e4e58d24ed4c174890ec96bd3
https://github.com/scummvm/scummvm/commit/830ef7f1f270874e4e58d24ed4c174890ec96bd3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Change hasFeature to use checkExtendedSaves function
Changed paths:
engines/mm/meta_engine.cpp
engines/mm/xeen/xeen.cpp
diff --git a/engines/mm/meta_engine.cpp b/engines/mm/meta_engine.cpp
index f283cca3e16..ede88e048cd 100644
--- a/engines/mm/meta_engine.cpp
+++ b/engines/mm/meta_engine.cpp
@@ -59,23 +59,8 @@ public:
};
bool MMMetaEngine::hasFeature(MetaEngineFeature f) const {
- return
- (f == kSavesUseExtendedFormat) ||
- (f == kSupportsListSaves) ||
- (f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo) ||
- (f == kSavesSupportCreationDate) ||
- (f == kSavesSupportPlayTime) ||
- (f == kSavesSupportThumbnail) ||
- (f == kSimpleSavesNames);
-}
-
-bool MM::Xeen::XeenEngine::hasFeature(EngineFeature f) const {
- return
- (f == kSupportsReturnToLauncher) ||
- (f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime);
+ return checkExtendedSaves(f) ||
+ (f == kSupportsLoadingDuringStartup);
}
Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
diff --git a/engines/mm/xeen/xeen.cpp b/engines/mm/xeen/xeen.cpp
index 063aab486c2..cd59dae2e75 100644
--- a/engines/mm/xeen/xeen.cpp
+++ b/engines/mm/xeen/xeen.cpp
@@ -118,6 +118,13 @@ bool XeenEngine::initialize() {
return true;
}
+bool XeenEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsReturnToLauncher) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
void XeenEngine::loadSettings() {
_gameWon[0] = ConfMan.hasKey("game_won") && ConfMan.getBool("game_won");
_gameWon[1] = ConfMan.hasKey("game_won2") && ConfMan.getBool("game_won2");
Commit: cfb76d8cc2271a1a653da7ddca03dd1654f5c434
https://github.com/scummvm/scummvm/commit/cfb76d8cc2271a1a653da7ddca03dd1654f5c434
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Change combat loop1 to selectMonster
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 53c0332db0e..2b74eb5b786 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -285,7 +285,7 @@ void Combat::selectParty() {
}
// At this point, a monster has precedence to attack
- loop1();
+ selectMonster();
}
void Combat::defeatedMonsters() {
@@ -319,7 +319,7 @@ void Combat::defeatedMonsters() {
combatDone();
}
-void Combat::loop1() {
+void Combat::selectMonster() {
for (uint i = 0; i < _remainingMonsters.size(); ++i) {
_monsterP = _remainingMonsters[i];
monsterIndexOf();
@@ -719,7 +719,7 @@ void Combat::checkParty() {
_party[i]->_checked = true;
}
- loop1();
+ selectMonster();
}
void Combat::fightMonster(int monsterNum) {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index ba3a2dafbd5..37f117d0c32 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -210,7 +210,7 @@ protected:
void defeatedMonsters();
void selectParty();
- void loop1();
+ void selectMonster();
void setTreasure();
void clearArrays();
bool moveMonsters();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 23dbc9907b3..ad4fa033341 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -190,7 +190,7 @@ void Combat::timeout() {
checkMonsterSpellDone();
break;
case WAITS_FOR_OPENING:
- loop1();
+ selectMonster();
break;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_activeSpells;
Commit: c02226bff5440d152dca9b759ac7e8d80424e21e
https://github.com/scummvm/scummvm/commit/c02226bff5440d152dca9b759ac7e8d80424e21e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Merge party/monsters turn selection methods into one
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 2b74eb5b786..b03713fdce5 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -261,31 +261,60 @@ void Combat::dispelParty() {
_monsterP = tmpM;
}
-void Combat::combatLoop() {
- if (_remainingMonsters.empty()) {
- defeatedMonsters();
- } else {
- selectParty();
- }
-}
+void Combat::combatLoop(bool checkMonstersFirst) {
+ for (;;) {
+ // Check if the monsters have all been defeated
+ if (_remainingMonsters.empty()) {
+ defeatedMonsters();
+ return;
+ }
-void Combat::selectParty() {
- for (uint i = 0; i < _party.size(); ++i) {
- Character &c = *_party[i];
- g_globals->_currCharacter = &c;
+ // Check for initial loop where monsters can be checked first
+ if (!checkMonstersFirst) {
+ for (uint i = 0; i < _party.size(); ++i) {
+ Character &c = *_party[i];
+ g_globals->_currCharacter = &c;
+
+ int speed = c._speed._current;
+ if (speed && speed >= _handicap2) {
+ if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
+ // Character is enabled
+ setMode(SELECT_OPTION);
+ return;
+ }
+ }
+ }
+ }
+
+ checkMonstersFirst = false;
+ for (uint i = 0; i < _remainingMonsters.size(); ++i) {
+ _monsterP = _remainingMonsters[i];
+ monsterIndexOf();
- int speed = c._speed._current;
- if (speed && speed >= _handicap2) {
- if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
- // Character is enabled
- setMode(SELECT_OPTION);
- return;
+ if (_monsterP->_speed && _monsterP->_speed >= _handicap3
+ && !_remainingMonsters[i]->_checked) {
+ _remainingMonsters[i]->_checked = true;
+
+ if (_remainingMonsters[i]->_status & (MONFLAG_ASLEEP | MONFLAG_HELD |
+ MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
+ checkMonsterFlees();
+ return;
+ }
}
}
- }
- // At this point, a monster has precedence to attack
- selectMonster();
+ // Decrease the handicap/speed threshold
+ if (_handicap2 == 1 && _handicap3 == 1) {
+ // End of the round
+ nextRound();
+ break;
+ } else {
+ if (_handicap2 != 1)
+ --_handicap2;
+ if (_handicap3 != 1)
+ --_handicap3;
+ }
+ }
}
void Combat::defeatedMonsters() {
@@ -319,33 +348,6 @@ void Combat::defeatedMonsters() {
combatDone();
}
-void Combat::selectMonster() {
- for (uint i = 0; i < _remainingMonsters.size(); ++i) {
- _monsterP = _remainingMonsters[i];
- monsterIndexOf();
-
- if (_monsterP->_speed && _monsterP->_speed >= _handicap3
- && !_remainingMonsters[i]->_checked) {
- _remainingMonsters[i]->_checked = true;
-
- if (_remainingMonsters[i]->_status & (MONFLAG_ASLEEP | MONFLAG_HELD |
- MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
- checkMonsterFlees();
- return;
- }
- }
- }
-
- if (_handicap2 == 1 && _handicap3 == 1) {
- nextRound();
- } else {
- if (_handicap2 != 1)
- --_handicap2;
- if (_handicap3 != 1)
- --_handicap3;
- }
-}
-
void Combat::setTreasure() {
_val7 = _monsterP->_field18;
_val6 = MAX(_val6, _val7);
@@ -719,7 +721,7 @@ void Combat::checkParty() {
_party[i]->_checked = true;
}
- selectMonster();
+ combatLoop(true);
}
void Combat::fightMonster(int monsterNum) {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 37f117d0c32..b96f183aea4 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -170,9 +170,10 @@ protected:
/*------- combat execution ------*/
/**
- * Start of the main combat loop
+ * Main combat loop that selects the next party
+ * member or monster to take their turn
*/
- void combatLoop();
+ void combatLoop(bool checkMonstersFirst = true);
/**
* Select treasure for a defeated monster
@@ -209,8 +210,6 @@ protected:
void checkMonsterActions();
void defeatedMonsters();
- void selectParty();
- void selectMonster();
void setTreasure();
void clearArrays();
bool moveMonsters();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index ad4fa033341..3cd13f3ac09 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -190,7 +190,7 @@ void Combat::timeout() {
checkMonsterSpellDone();
break;
case WAITS_FOR_OPENING:
- selectMonster();
+ combatLoop(true);
break;
case DEFEATED_MONSTERS: {
auto &spells = g_globals->_activeSpells;
Commit: 5209840a0f0c34f2f996e9a4028ea9a6e7ea1d29
https://github.com/scummvm/scummvm/commit/5209840a0f0c34f2f996e9a4028ea9a6e7ea1d29
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Fix selecting correct combat char
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b03713fdce5..1d8abf6ea80 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -273,10 +273,12 @@ void Combat::combatLoop(bool checkMonstersFirst) {
if (!checkMonstersFirst) {
for (uint i = 0; i < _party.size(); ++i) {
Character &c = *_party[i];
- g_globals->_currCharacter = &c;
-
int speed = c._speed._current;
- if (speed && speed >= _handicap2) {
+
+ if (speed && speed >= _handicap2 && !c._checked) {
+ _currentChar = i;
+ g_globals->_currCharacter = &c;
+
if (!(c._condition & (BLINDED | SILENCED | DISEASED | POISONED))) {
// Character is enabled
setMode(SELECT_OPTION);
@@ -314,6 +316,7 @@ void Combat::combatLoop(bool checkMonstersFirst) {
if (_handicap3 != 1)
--_handicap3;
}
+ assert(_handicap2 >= 1 && _handicap3 >= 1);
}
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index b96f183aea4..3b1a069a8ef 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -173,7 +173,7 @@ protected:
* Main combat loop that selects the next party
* member or monster to take their turn
*/
- void combatLoop(bool checkMonstersFirst = true);
+ void combatLoop(bool checkMonstersFirst = false);
/**
* Select treasure for a defeated monster
Commit: cbbdff2d990add891e4bb14ee825f78d555ad3fd
https://github.com/scummvm/scummvm/commit/cbbdff2d990add891e4bb14ee825f78d555ad3fd
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:50+01:00
Commit Message:
MM: MM1: Fix calculating party handicap
Changed paths:
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 1d8abf6ea80..121d8df4521 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -216,7 +216,7 @@ void Combat::setupHandicap() {
return;
}
} else if (val > _handicap1) {
- _handicap4 -= _handicap1;
+ _handicap4 = val - _handicap1;
if (_handicap4) {
_handicap = HANDICAP_PARTY;
Commit: fbe6f34e11c2769b2b58c65d10a2ee91be12c555
https://github.com/scummvm/scummvm/commit/fbe6f34e11c2769b2b58c65d10a2ee91be12c555
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Fix Exchange combat option
Changed paths:
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 3cd13f3ac09..6e86ebd0492 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -544,7 +544,7 @@ void Combat::writeParty() {
for (uint i = 0; i < _party.size(); ++i) {
writeChar(1 + 21 * (i % 2), 16 + (i / 2), '1' + i);
writeString(") ");
- writeString(g_globals->_party[i]._name);
+ writeString(_party[i]->_name);
}
}
@@ -804,6 +804,7 @@ void Combat::setOption(SelectedOption option) {
KeybindingMode::KBMODE_PARTY_MENUS :
KeybindingMode::KBMODE_MENUS);
_option = option;
+ redraw();
}
void Combat::displaySpellResult(const InfoMessage &msg) {
Commit: 8bbd2ed31a6b8088c5e51bac4f457a16e37e632c
https://github.com/scummvm/scummvm/commit/8bbd2ed31a6b8088c5e51bac4f457a16e37e632c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Properly implement character stats view within combat
Changed paths:
A engines/mm/mm1/views/character_view_combat.cpp
A engines/mm/mm1/views/character_view_combat.h
engines/mm/mm1/views/character_view.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/dialogs.h
engines/mm/mm1/views/encounter.cpp
engines/mm/mm1/views/title.cpp
engines/mm/module.mk
diff --git a/engines/mm/mm1/views/character_view.h b/engines/mm/mm1/views/character_view.h
index 035b272e440..33c2755dd01 100644
--- a/engines/mm/mm1/views/character_view.h
+++ b/engines/mm/mm1/views/character_view.h
@@ -30,14 +30,14 @@ namespace MM1 {
namespace Views {
/**
- * Character management dialog
+ * Character view from the inn screen
*/
class CharacterView : public CharacterBase {
public:
CharacterView() : CharacterBase("CharacterView") {}
virtual ~CharacterView() {}
- void draw() {
+ void draw() override {
CharacterBase::draw();
escToGoBack();
}
diff --git a/engines/mm/mm1/views/character_view_combat.cpp b/engines/mm/mm1/views/character_view_combat.cpp
new file mode 100644
index 00000000000..3951bee3348
--- /dev/null
+++ b/engines/mm/mm1/views/character_view_combat.cpp
@@ -0,0 +1,72 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views/character_view_combat.h"
+#include "mm/mm1/utils/strings.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+void CharacterViewCombat::show(const Common::Array<Character *> &party) {
+ CharacterViewCombat *view = static_cast<CharacterViewCombat *>(
+ g_events->findView("CharacterViewCombat"));
+ view->_party = party;
+ view->addView();
+}
+
+bool CharacterViewCombat::msgFocus(const FocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_PARTY_MENUS);
+ return CharacterBase::msgFocus(msg);
+}
+
+bool CharacterViewCombat::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return CharacterBase::msgUnfocus(msg);
+}
+
+void CharacterViewCombat::draw() {
+ CharacterBase::draw();
+
+ writeString(12, 22, Common::String::format("'1'-'%c' %s",
+ '0' + _party.size(), STRING["dialogs.quick_ref.to_view"].c_str()));
+ escToGoBack();
+}
+
+bool CharacterViewCombat::msgAction(const ActionMessage &msg) {
+ if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+ msg._action <= KEYBIND_VIEW_PARTY6) {
+ uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
+ if (charNum < _party.size()) {
+ g_globals->_currCharacter = _party[charNum];
+ redraw();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/character_view_combat.h b/engines/mm/mm1/views/character_view_combat.h
new file mode 100644
index 00000000000..3ba3d21976b
--- /dev/null
+++ b/engines/mm/mm1/views/character_view_combat.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_CHARACTER_VIEW_COMBAT_H
+#define MM1_VIEWS_CHARACTER_VIEW_COMBAT_H
+
+#include "common/array.h"
+#include "mm/mm1/data/character.h"
+#include "mm/mm1/views/character_base.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+
+/**
+ * Character info view within combat, that allows
+ * switching between characters
+ */
+class CharacterViewCombat : public CharacterBase {
+private:
+ Common::Array<Character *> _party;
+public:
+ CharacterViewCombat() : CharacterBase("CharacterViewCombat") {}
+ virtual ~CharacterViewCombat() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+ void draw() override;
+ bool msgAction(const ActionMessage &msg) override;
+
+ static void show(const Common::Array<Character *> &party);
+};
+
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 6e86ebd0492..cf3633919a0 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views/combat.h"
+#include "mm/mm1/views/character_view_combat.h"
#include "mm/mm1/game/encounter.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
@@ -57,17 +58,9 @@ void Combat::disableAttacks() {
}
bool Combat::msgFocus(const FocusMessage &msg) {
- // Clear combat data
- clear();
-
+ g_globals->_currCharacter = _party[_currentChar];
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
- loadMonsters();
- setupCanAttacks();
- setupHandicap();
-
- combatLoop();
-
return true;
}
@@ -77,7 +70,19 @@ bool Combat::msgUnfocus(const UnfocusMessage &msg) {
}
bool Combat::msgGame(const GameMessage &msg) {
- if (msg._name == "SPELL_RESULT") {
+ if (msg._name == "COMBAT") {
+ // Clear combat data
+ clear();
+
+ loadMonsters();
+ setupCanAttacks();
+ setupHandicap();
+
+ addView();
+ combatLoop();
+ return true;
+
+ } else if (msg._name == "SPELL_RESULT") {
displaySpellResult(msg._stringValue);
return true;
}
@@ -274,7 +279,7 @@ bool Combat::msgAction(const ActionMessage &msg) {
exchangeWith(charNum);
} else {
g_globals->_currCharacter = _party[charNum];
- addView("CharacterInfo");
+ CharacterViewCombat::show(_party);
}
return true;
}
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index 2afc8e72062..ed11bdd8bdc 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -25,6 +25,7 @@
#include "mm/mm1/events.h"
#include "mm/mm1/views/are_you_ready.h"
#include "mm/mm1/views/bash.h"
+#include "mm/mm1/views/character_view_combat.h"
#include "mm/mm1/views/combat.h"
#include "mm/mm1/views/create_characters.h"
#include "mm/mm1/views/dead.h"
@@ -36,6 +37,7 @@
#include "mm/mm1/views/quick_ref.h"
#include "mm/mm1/views/title.h"
#include "mm/mm1/views/character_info.h"
+#include "mm/mm1/views/character_view_combat.h"
#include "mm/mm1/views/characters.h"
#include "mm/mm1/views/rest.h"
#include "mm/mm1/views/search.h"
@@ -87,6 +89,7 @@ struct Dialogs {
private:
Views::AreYouReady _areYouReady;
Views::Bash _bash;
+ Views::CharacterViewCombat _characterViewCombat;
Views::Combat _combat;
Views::CreateCharacters _createCharacters;
Views::Dead _dead;
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index a2f6cf56dad..d42d9eb6063 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -171,7 +171,7 @@ void Encounter::timeout() {
case BATTLE:
// Switch to combat view
- replaceView("Combat");
+ send("Combat", GameMessage("COMBAT"));
break;
default:
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index 08e1ed1bc15..b366229ad63 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -145,7 +145,6 @@ bool Title::msgKeypress(const KeypressMessage &msg) {
return true;
}
-
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 7973da7c867..6bbd5a972f4 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -89,6 +89,7 @@ MODULE_OBJS := \
mm1/views/character_base.o \
mm1/views/character_info.o \
mm1/views/character_manage.o \
+ mm1/views/character_view_combat.o \
mm1/views/characters.o \
mm1/views/combat.o \
mm1/views/create_characters.o \
Commit: 7e2ede96a17c431915680dd4e414f730488301fb
https://github.com/scummvm/scummvm/commit/7e2ede96a17c431915680dd4e414f730488301fb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Fix retreating from combat
Changed paths:
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
engines/mm/mm1/views/encounter.cpp
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 3b1a069a8ef..115df32a9bd 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -100,6 +100,11 @@ protected:
*/
virtual void setMode(Mode newMode) = 0;
+ /**
+ * Does final cleanup when combat is done
+ */
+ virtual void combatDone();
+
/**
* Clear all the combat variables
*/
@@ -289,11 +294,6 @@ protected:
*/
void retreat();
- /**
- * Does final cleanup when combat is done
- */
- void combatDone();
-
private:
void spellFailed();
void destroyMonster();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index cf3633919a0..0048896b8b3 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -820,6 +820,11 @@ void Combat::displaySpellResult(const InfoMessage &msg) {
setMode(SPELL_RESULT);
}
+void Combat::combatDone() {
+ Game::Combat::combatDone();
+ close();
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index bc6ab71d8b9..6e44568fc72 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -209,6 +209,12 @@ protected:
* Sets a new display mode
*/
void setMode(Mode newMode) override;
+
+ /**
+ * Does final cleanup when combat is done
+ */
+ void combatDone() override;
+
public:
Combat();
virtual ~Combat() {}
diff --git a/engines/mm/mm1/views/encounter.cpp b/engines/mm/mm1/views/encounter.cpp
index d42d9eb6063..5618c15ad51 100644
--- a/engines/mm/mm1/views/encounter.cpp
+++ b/engines/mm/mm1/views/encounter.cpp
@@ -171,6 +171,7 @@ void Encounter::timeout() {
case BATTLE:
// Switch to combat view
+ close();
send("Combat", GameMessage("COMBAT"));
break;
Commit: b7c1049c4657ab7e6af63f27e47e68ec376295c0
https://github.com/scummvm/scummvm/commit/b7c1049c4657ab7e6af63f27e47e68ec376295c0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Char targeted spells in combat use now global _combatParty
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/globals.h
engines/mm/mm1/views/character_view_combat.cpp
engines/mm/mm1/views/character_view_combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 121d8df4521..c6b08b8f588 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -80,9 +80,9 @@ void Combat::clear() {
_roundNum = 1;
_monstersCount = _remainingMonsters.size();
- _party.clear();
+ g_globals->_combatParty.clear();
for (uint i = 0; i < g_globals->_party.size(); ++i)
- _party.push_back(&g_globals->_party[i]);
+ g_globals->_combatParty.push_back(&g_globals->_party[i]);
}
void Combat::loadMonsters() {
@@ -128,16 +128,16 @@ void Combat::setupCanAttacks() {
const Encounter &enc = g_globals->_encounters;
const Maps::Map &map = *g_maps->_currentMap;
- for (uint i = 0; i < _party.size(); ++i)
- _party[i]->_canAttack = false;
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i)
+ g_globals->_combatParty[i]->_canAttack = false;
if ((int8)map[Maps::MAP_ID] < 0) {
if (enc._encounterType != FORCE_SURPRISED) {
- for (uint i = 0; i < _party.size(); ++i) {
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
if (i < (MAX_PARTY_SIZE - 1)) {
- _party[i]->_canAttack = true;
+ g_globals->_combatParty[i]->_canAttack = true;
} else {
- _party[MAX_PARTY_SIZE - 1]->_canAttack =
+ g_globals->_combatParty[MAX_PARTY_SIZE - 1]->_canAttack =
getRandomNumber(100) <= 10;
}
}
@@ -147,20 +147,20 @@ void Combat::setupCanAttacks() {
}
} else {
if (enc._encounterType != FORCE_SURPRISED) {
- _party[0]->_canAttack = true;
- if (_party.size() > 1)
- _party[1]->_canAttack = true;
- if (_party.size() > 2)
+ g_globals->_combatParty[0]->_canAttack = true;
+ if (g_globals->_combatParty.size() > 1)
+ g_globals->_combatParty[1]->_canAttack = true;
+ if (g_globals->_combatParty.size() > 2)
checkLeftWall();
- if (_party.size() > 3)
+ if (g_globals->_combatParty.size() > 3)
checkRightWall();
- if (_party.size() > 4) {
- if (_party[2]->_canAttack && getRandomNumber(100) <= 5)
- _party[4]->_canAttack = true;
+ if (g_globals->_combatParty.size() > 4) {
+ if (g_globals->_combatParty[2]->_canAttack && getRandomNumber(100) <= 5)
+ g_globals->_combatParty[4]->_canAttack = true;
}
- if (_party.size() > 5) {
- if (_party[3]->_canAttack && getRandomNumber(100) <= 5)
- _party[5]->_canAttack = true;
+ if (g_globals->_combatParty.size() > 5) {
+ if (g_globals->_combatParty[3]->_canAttack && getRandomNumber(100) <= 5)
+ g_globals->_combatParty[5]->_canAttack = true;
}
setupAttackerVal();
@@ -171,16 +171,16 @@ void Combat::setupCanAttacks() {
// Entire party is allowed to attack, I guess
// because the monsters are surrounding the party,
// placing them within reach
- for (uint i = 0; i < _party.size(); ++i)
- _party[i]->_canAttack = true;
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i)
+ g_globals->_combatParty[i]->_canAttack = true;
setupAttackerVal();
}
void Combat::setupAttackerVal() {
_attackerVal = 0;
- for (uint i = 0; i < _party.size(); ++i) {
- if (_party[i]->_canAttack)
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ if (g_globals->_combatParty[i]->_canAttack)
++_attackerVal;
}
@@ -190,14 +190,14 @@ void Combat::setupAttackerVal() {
void Combat::checkLeftWall() {
Maps::Maps &maps = *g_maps;
- _party[2]->_canAttack = !(maps._currentWalls & maps._leftMask) ||
+ g_globals->_combatParty[2]->_canAttack = !(maps._currentWalls & maps._leftMask) ||
getRandomNumber(100) <= 25;
}
void Combat::checkRightWall() {
Maps::Maps &maps = *g_maps;
- _party[3]->_canAttack = !(maps._currentWalls & maps._rightMask) ||
+ g_globals->_combatParty[3]->_canAttack = !(maps._currentWalls & maps._rightMask) ||
getRandomNumber(100) <= 25;
}
@@ -240,8 +240,8 @@ void Combat::dispelParty() {
Character *tmpC = g_globals->_currCharacter;
Monster *tmpM = _monsterP;
- for (uint i = 0; i < _party.size(); ++i) {
- Character &c = *_party[i];
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ Character &c = *g_globals->_combatParty[i];
g_globals->_currCharacter = &c;
c.updateAttributes();
c.updateAC();
@@ -271,8 +271,8 @@ void Combat::combatLoop(bool checkMonstersFirst) {
// Check for initial loop where monsters can be checked first
if (!checkMonstersFirst) {
- for (uint i = 0; i < _party.size(); ++i) {
- Character &c = *_party[i];
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ Character &c = *g_globals->_combatParty[i];
int speed = c._speed._current;
if (speed && speed >= _handicap2 && !c._checked) {
@@ -333,16 +333,16 @@ void Combat::defeatedMonsters() {
}
// Count number of active characters
- for (uint i = 0; i < _party.size(); ++i) {
- if (!(_party[i]->_condition & BAD_CONDITION))
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ if (!(g_globals->_combatParty[i]->_condition & BAD_CONDITION))
++activeCharCount;
}
// Split the experience between the active characters
_totalExperience /= activeCharCount;
- for (uint i = 0; i < _party.size(); ++i) {
- if (!(_party[i]->_condition & BAD_CONDITION))
- _party[i]->_exp += _totalExperience;
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ if (!(g_globals->_combatParty[i]->_condition & BAD_CONDITION))
+ g_globals->_combatParty[i]->_exp += _totalExperience;
}
// Update the party's characters
@@ -434,7 +434,7 @@ void Combat::nextRound() {
clearArrays();
g_globals->_party.updateAC();
- _partyIndex = getRandomNumber(_party.size());
+ _partyIndex = getRandomNumber(g_globals->_combatParty.size());
updateHighestLevel();
setMode(NEXT_ROUND);
@@ -459,8 +459,8 @@ void Combat::nextRound3() {
}
void Combat::clearArrays() {
- for (uint i = 0; i < _party.size(); ++i)
- _party[i]->_checked = false;
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i)
+ g_globals->_combatParty[i]->_checked = false;
for (uint i = 0; i < _remainingMonsters.size(); ++i)
_remainingMonsters[i]->_checked = false;
@@ -469,7 +469,7 @@ void Combat::clearArrays() {
void Combat::updateHighestLevel() {
Encounter &enc = g_globals->_encounters;
- for (uint i = 0; i < _party.size(); ++i) {
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
Character &c = g_globals->_party[i];
g_globals->_currCharacter = &c;
@@ -718,10 +718,10 @@ void Combat::checkParty() {
return;
// Update the array for the party
- for (uint i = 0; i < _party.size(); ++i) {
- const Character &c = *_party[i];
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ const Character &c = *g_globals->_combatParty[i];
if ((c._condition & BAD_CONDITION) || !c._hpBase)
- _party[i]->_checked = true;
+ g_globals->_combatParty[i]->_checked = true;
}
combatLoop(true);
@@ -860,7 +860,7 @@ void Combat::attackMonster(int monsterNum) {
_message.push_back(Line(0, 1, STRING["dialogs.combat.weapon_no_effect"]));
}
- _party[_currentChar]->_checked = true;
+ g_globals->_combatParty[_currentChar]->_checked = true;
setMode(CHAR_ATTACKS);
}
@@ -1074,7 +1074,7 @@ void Combat::iterateMonsters2Inner() {
}
void Combat::characterDone() {
- _party[_currentChar]->_checked = true;
+ g_globals->_combatParty[_currentChar]->_checked = true;
combatLoop();
}
@@ -1086,7 +1086,7 @@ void Combat::resetDestMonster() {
}
void Combat::spellFailed() {
- _party[_currentChar]->_checked = true;
+ g_globals->_combatParty[_currentChar]->_checked = true;
SoundMessage msg(10, 2, Common::String::format("*** %s ***",
STRING["spells.failed"].c_str()));
@@ -1126,7 +1126,7 @@ void Combat::turnUndead() {
displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
}
- _party[_currentChar]->_checked = true;
+ g_globals->_combatParty[_currentChar]->_checked = true;
}
void Combat::destroyMonster() {
@@ -1239,7 +1239,7 @@ void Combat::holyWord() {
displaySpellResult(InfoMessage(5, 1, STRING["spells.monsters_destroyed"]));
else
displaySpellResult(InfoMessage(15, 1, STRING["spells.no_effect"]));
- _party[_currentChar]->_checked = true;
+ g_globals->_combatParty[_currentChar]->_checked = true;
}
#define COL2 21
@@ -1328,8 +1328,8 @@ void Combat::lightningBolt() {
}
void Combat::makeRoom() {
- for (uint i = 0; i < MIN(_party.size(), 5U); ++i)
- _party[i]->_canAttack = true;
+ for (uint i = 0; i < MIN(g_globals->_combatParty.size(), 5U); ++i)
+ g_globals->_combatParty[i]->_canAttack = true;
}
void Combat::slow() {
@@ -1509,7 +1509,7 @@ void Combat::selectMonsterTarget() {
// Find a party position that can attack
int wrapCount = 0;
- while (!_party[idx]->_canAttack) {
+ while (!g_globals->_combatParty[idx]->_canAttack) {
if (++idx >= g_globals->_party.size()) {
idx = 0;
if (++wrapCount > 1)
@@ -1532,8 +1532,8 @@ void Combat::selectMonsterTarget() {
// At this point, fall back on a generic display message
// that the monster infiltrates the ranks, which basically
// means enabling the whole party to be able to attack directly
- for (uint i = 0; i < _party.size(); ++i)
- _party[i]->_canAttack = true;
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i)
+ g_globals->_combatParty[i]->_canAttack = true;
_attackerVal = g_globals->_party.size() * 2;
setMode(INFILTRATION);
@@ -1553,11 +1553,11 @@ void Combat::cast() {
}
void Combat::exchangeWith(int charNum) {
- _party[_currentChar]->_checked = true;
- Character *c1 = _party[_currentChar];
- Character *c2 = _party[charNum];
- _party[_currentChar] = c2;
- _party[charNum] = c1;
+ g_globals->_combatParty[_currentChar]->_checked = true;
+ Character *c1 = g_globals->_combatParty[_currentChar];
+ Character *c2 = g_globals->_combatParty[charNum];
+ g_globals->_combatParty[_currentChar] = c2;
+ g_globals->_combatParty[charNum] = c1;
_currentChar = charNum;
combatLoop();
@@ -1598,7 +1598,7 @@ void Combat::combatDone() {
g_globals->_activeSpells._s.power_shield = 0;
// Rearrange the party to match the combat order
- g_globals->_party.rearrange(_party);
+ g_globals->_party.rearrange(g_globals->_combatParty);
}
} // namespace Game
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 115df32a9bd..4a45be1f2e2 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -37,7 +37,6 @@ class Combat : public MonsterTouch {
protected:
Common::Array<Line> _message;
int _monstersCount = 0;
- Common::Array<Character *> _party;
Monster *_monsterP;
bool _treasureFlags[MAX_PARTY_SIZE];
int _val1;
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 5860ad4098b..cc4b174f7a2 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -44,6 +44,7 @@ class Globals : public GameState {
public:
StringsData _strings;
Roster _roster;
+ Common::Array<Character *> _combatParty;
Character *_currCharacter = nullptr;
Item _currItem;
ItemsArray _items;
diff --git a/engines/mm/mm1/views/character_view_combat.cpp b/engines/mm/mm1/views/character_view_combat.cpp
index 3951bee3348..9d4bcae3d8a 100644
--- a/engines/mm/mm1/views/character_view_combat.cpp
+++ b/engines/mm/mm1/views/character_view_combat.cpp
@@ -27,13 +27,6 @@ namespace MM {
namespace MM1 {
namespace Views {
-void CharacterViewCombat::show(const Common::Array<Character *> &party) {
- CharacterViewCombat *view = static_cast<CharacterViewCombat *>(
- g_events->findView("CharacterViewCombat"));
- view->_party = party;
- view->addView();
-}
-
bool CharacterViewCombat::msgFocus(const FocusMessage &msg) {
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_PARTY_MENUS);
return CharacterBase::msgFocus(msg);
@@ -48,7 +41,7 @@ void CharacterViewCombat::draw() {
CharacterBase::draw();
writeString(12, 22, Common::String::format("'1'-'%c' %s",
- '0' + _party.size(), STRING["dialogs.quick_ref.to_view"].c_str()));
+ '0' + g_globals->_combatParty.size(), STRING["dialogs.quick_ref.to_view"].c_str()));
escToGoBack();
}
@@ -56,8 +49,8 @@ bool CharacterViewCombat::msgAction(const ActionMessage &msg) {
if (msg._action >= KEYBIND_VIEW_PARTY1 &&
msg._action <= KEYBIND_VIEW_PARTY6) {
uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
- if (charNum < _party.size()) {
- g_globals->_currCharacter = _party[charNum];
+ if (charNum < g_globals->_combatParty.size()) {
+ g_globals->_currCharacter = g_globals->_combatParty[charNum];
redraw();
}
diff --git a/engines/mm/mm1/views/character_view_combat.h b/engines/mm/mm1/views/character_view_combat.h
index 3ba3d21976b..95d3e7b43f6 100644
--- a/engines/mm/mm1/views/character_view_combat.h
+++ b/engines/mm/mm1/views/character_view_combat.h
@@ -35,8 +35,6 @@ namespace Views {
* switching between characters
*/
class CharacterViewCombat : public CharacterBase {
-private:
- Common::Array<Character *> _party;
public:
CharacterViewCombat() : CharacterBase("CharacterViewCombat") {}
virtual ~CharacterViewCombat() {}
@@ -45,8 +43,6 @@ public:
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgAction(const ActionMessage &msg) override;
-
- static void show(const Common::Array<Character *> &party);
};
} // namespace Views
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 0048896b8b3..fbfba33ec0d 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -58,7 +58,7 @@ void Combat::disableAttacks() {
}
bool Combat::msgFocus(const FocusMessage &msg) {
- g_globals->_currCharacter = _party[_currentChar];
+ g_globals->_currCharacter = g_globals->_combatParty[_currentChar];
MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
return true;
@@ -273,13 +273,13 @@ bool Combat::msgAction(const ActionMessage &msg) {
case KEYBIND_VIEW_PARTY5:
case KEYBIND_VIEW_PARTY6: {
uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
- if (charNum < _party.size()) {
+ if (charNum < g_globals->_combatParty.size()) {
if (_option == OPTION_EXCHANGE) {
- if (_party[charNum] != g_globals->_currCharacter)
+ if (g_globals->_combatParty[charNum] != g_globals->_currCharacter)
exchangeWith(charNum);
} else {
- g_globals->_currCharacter = _party[charNum];
- CharacterViewCombat::show(_party);
+ g_globals->_currCharacter = g_globals->_combatParty[charNum];
+ addView("CharacterViewCombat");
}
return true;
}
@@ -366,7 +366,7 @@ void Combat::writeAllOptions() {
writeChar(3 + 4 * (_currentChar % 2), 3 + (_currentChar / 2),
(unsigned char)'1' + _currentChar + 0x80);
- bool canAttack = _party[_currentChar]->_canAttack;
+ bool canAttack = g_globals->_combatParty[_currentChar]->_canAttack;
if (canAttack) {
writeAttackOptions();
_allowAttack = true;
@@ -402,7 +402,7 @@ void Combat::writeExchangeSelect() {
resetBottom();
writeString(7, 20, Common::String::format(
STRING["dialogs.combat.exchange_places"].c_str(),
- '0' + _party.size()));
+ '0' + g_globals->_combatParty.size()));
escToGoBack(12, 23);
}
@@ -479,9 +479,9 @@ void Combat::writeRound() {
}
void Combat::writePartyNumbers() {
- for (uint i = 0; i < _party.size(); ++i) {
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
writeChar(2 + 4 * (i % 2), 3 + (i / 2),
- _party[i]->_canAttack ? '+' : ' ');
+ g_globals->_combatParty[i]->_canAttack ? '+' : ' ');
writeChar('1' + i);
}
}
@@ -546,10 +546,10 @@ void Combat::writeDots() {
void Combat::writeParty() {
clearPartyArea();
- for (uint i = 0; i < _party.size(); ++i) {
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
writeChar(1 + 21 * (i % 2), 16 + (i / 2), '1' + i);
writeString(") ");
- writeString(_party[i]->_name);
+ writeString(g_globals->_combatParty[i]->_name);
}
}
@@ -714,7 +714,7 @@ void Combat::delay() {
}
void Combat::exchange() {
- if (_party.size() > 1)
+ if (g_globals->_combatParty.size() > 1)
setOption(OPTION_EXCHANGE);
}
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index cb4edf0a4e7..af6d4bd576b 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -172,8 +172,11 @@ bool CastSpell::msgAction(const ActionMessage &msg) {
msg._action >= KEYBIND_VIEW_PARTY1 &&
msg._action <= KEYBIND_VIEW_PARTY6) {
uint charIndex = (int)(msg._action - KEYBIND_VIEW_PARTY1);
- if (charIndex < g_globals->_party.size())
- performSpell(&g_globals->_party[charIndex]);
+ if (charIndex < g_globals->_party.size()) {
+ Character *c = isInCombat() ? g_globals->_combatParty[charIndex] :
+ &g_globals->_party[charIndex];
+ performSpell(c);
+ }
}
return true;
Commit: 3aae2eb5547b846a31961c6d36a63908c245571d
https://github.com/scummvm/scummvm/commit/3aae2eb5547b846a31961c6d36a63908c245571d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Fix display of char attack messages
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index c6b08b8f588..4479e8d09d9 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -838,6 +838,10 @@ void Combat::attackMonster(int monsterNum) {
if (_isShooting && c._class == ARCHER)
_attackAttr2._current += (c._level + 1) / 2;
+ // Mark the character as having attacked this round
+ g_globals->_combatParty[_currentChar]->_checked = true;
+
+ // Can the attack succeed?
if (_attackAttr1._current || !(_monsterP->_field1a & FIELD1A_80)) {
if (enc._monsterList[_monsterIndex]._status & (MONFLAG_ASLEEP |
MONFLAG_HELD | MONFLAG_WEBBED | MONFLAG_PARALYZED))
@@ -856,12 +860,12 @@ void Combat::attackMonster(int monsterNum) {
addAttackDamage();
if (_damage)
updateMonsterStatus();
+
+ setMode(CHAR_ATTACKS);
+
} else {
- _message.push_back(Line(0, 1, STRING["dialogs.combat.weapon_no_effect"]));
+ setMode(NO_EFFECT);
}
-
- g_globals->_combatParty[_currentChar]->_checked = true;
- setMode(CHAR_ATTACKS);
}
void Combat::addAttackDamage() {
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 4a45be1f2e2..2e29877d486 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -72,7 +72,7 @@ protected:
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL,
CHAR_ATTACKS, MONSTER_ATTACK, INFILTRATION,
- WAITS_FOR_OPENING, SPELL_RESULT
+ WAITS_FOR_OPENING, SPELL_RESULT, NO_EFFECT
};
Mode _mode = SELECT_OPTION;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index fbfba33ec0d..8a828ac6ebd 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -135,6 +135,10 @@ void Combat::draw() {
writeCharAttackDamage();
delaySeconds(3);
return;
+ case NO_EFFECT:
+ writeCharAttackNoEffect();
+ delaySeconds(3);
+ return;
default:
break;
}
@@ -179,6 +183,7 @@ void Combat::timeout() {
break;
case MONSTERS_AFFECTED:
case CHAR_ATTACKS:
+ case NO_EFFECT:
combatLoop();
break;
case MONSTER_FLEES:
@@ -752,7 +757,23 @@ void Combat::writeMessage() {
}
void Combat::writeCharAttackDamage() {
- writeString(0, 0, Common::String::format("%s %s %s",
+ resetBottom();
+
+ writeString(0, 20, Common::String::format("%s %s %s",
+ g_globals->_currCharacter->_name,
+ STRING[_isShooting ? "dialogs.combat.shoots" :
+ "dialogs.combat.attacks"].c_str(),
+ _monsterP->_name.c_str()
+ ));
+ _isShooting = false;
+
+ writeString(0, 21, getAttackString());
+}
+
+void Combat::writeCharAttackNoEffect() {
+ resetBottom();
+
+ writeString(0, 20, Common::String::format("%s %s %s",
g_globals->_currCharacter->_name,
STRING[_isShooting ? "dialogs.combat.shoots" :
"dialogs.combat.attacks"].c_str(),
@@ -760,7 +781,7 @@ void Combat::writeCharAttackDamage() {
));
_isShooting = false;
- writeString(0, 1, getAttackString());
+ writeString(0, 21, STRING["dialogs.combat.weapon_no_effect"]);
}
Common::String Combat::getAttackString() {
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 6e44568fc72..6d61dbf628b 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -174,6 +174,11 @@ private:
*/
void writeCharAttackDamage();
+ /**
+ * Write message for character attack having no effect
+ */
+ void writeCharAttackNoEffect();
+
/**
* Get attack damage string
*/
Commit: 01d8d1abc77dceb00a455d596b31da0696b07b07
https://github.com/scummvm/scummvm/commit/01d8d1abc77dceb00a455d596b31da0696b07b07
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Strip off trailing spaces on monster names
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/views/combat.cpp
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index e49d3ffe716..61718205a5c 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -365,6 +365,7 @@ dialogs:
party_plus: "PARTY +"
monster_plus: "MONSTER +"
and_goes_down: "AND GOES DOWN!!!"
+ goes_down: "GOES DOWN!!!"
dies: "DIES!"
defeating1: "! FOR DEFEATING THE MONSTERS !"
defeating2: "! EACH SURVIVOR RECEIVES !"
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index 82919bcf996..e46489d5379 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -38,8 +38,10 @@ bool Monsters::load() {
assert(line.size() > 20 && line[0] == '"' && line[16] == '"');
mon._name = Common::String(line.c_str() + 1, line.c_str() + 15);
- line = Common::String(line.c_str() + 17);
+ while (mon._name.hasSuffix(" "))
+ mon._name.deleteLastChar();
+ line = Common::String(line.c_str() + 17);
mon._count = getNextValue(line);
mon._fleeThreshold = getNextValue(line);
mon._defaultHP = getNextValue(line);
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 4479e8d09d9..5d16e4dc8b3 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -889,7 +889,7 @@ void Combat::updateMonsterStatus() {
if (val <= 0) {
enc._monsterList[_monsterIndex]._hp = 0;
enc._monsterList[_monsterIndex]._status = MONFLAG_DEAD;
- warning("TODO: message that monster goes down");
+
} else {
enc._monsterList[_monsterIndex]._hp = val;
enc._monsterList[_monsterIndex]._status &= ~(MONFLAG_ASLEEP | MONFLAG_HELD);
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 8a828ac6ebd..93a5697dff3 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -768,6 +768,12 @@ void Combat::writeCharAttackDamage() {
_isShooting = false;
writeString(0, 21, getAttackString());
+
+ if (_monsterP->_status == MONFLAG_DEAD) {
+ writeString(0, 22, Common::String::format("%s %s",
+ _monsterP->_name.c_str(),
+ STRING["dialogs.combat.goes_down"].c_str()));
+ }
}
void Combat::writeCharAttackNoEffect() {
Commit: 91988d6f61846efa9f68b47a5f816103843fc030
https://github.com/scummvm/scummvm/commit/91988d6f61846efa9f68b47a5f816103843fc030
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Fix calculating monster AC and char damage amounts
Changed paths:
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 5d16e4dc8b3..2abdeb96de7 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -758,6 +758,7 @@ void Combat::attackMonster(int monsterNum) {
Character &c = *g_globals->_currCharacter;
_attackerLevel = c._level._current;
+ _destAC = _monsterP->_ac;
if (c._class >= CLERIC) {
_attackerLevel >>= 1;
@@ -853,8 +854,10 @@ void Combat::attackMonster(int monsterNum) {
}
if (g_globals->_activeSpells._s.cursed) {
- if (++_destAC > 255)
- _destAC = 200;
+ int destAC = _destAC + (int)g_globals->_activeSpells._s.cursed;
+ if (destAC > 255)
+ destAC = 200;
+ _destAC = destAC;
}
addAttackDamage();
@@ -876,7 +879,7 @@ void Combat::addAttackDamage() {
for (int i = 0; i < _numberOfTimes; ++i) {
int val = getRandomNumber(20);
if (val == 20 || (val != 1 && (val + _attackerLevel) >= _destAC)) {
- _damage = MAX(_damage + (int)_attackAttr2._current +
+ _damage = MIN(_damage + (int)_attackAttr2._current +
getRandomNumber(_attackAttr2._base), 255);
++_timesHit;
}
Commit: 373b6fac9ca67683351f65f0a3b023f5b2c8b065
https://github.com/scummvm/scummvm/commit/373b6fac9ca67683351f65f0a3b023f5b2c8b065
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: Fixes for combat shooting
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 61718205a5c..bac93d25e74 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -385,8 +385,8 @@ dialogs:
point: "POINT"
points: "POINTS"
of_damage: "OF DAMAGE!"
- fight_which: "FIGHT WHICH 'A'-'%d'?"
- shoot_which: "SHOOT WHICH 'A'-'%d'?"
+ fight_which: "FIGHT WHICH 'A'-'%c'?"
+ shoot_which: "SHOOT WHICH 'A'-'%c'?"
set_delay: "SET DELAY (0-9):"
delay_currently: "(CURRENTLY= %d)"
infiltration: "INFILTRATES THE RANKS!"
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 93a5697dff3..5c94917e4df 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -232,7 +232,7 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
case OPTION_FIGHT:
case OPTION_SHOOT:
if (msg.keycode >= Common::KEYCODE_a &&
- msg.keycode < (int)(Common::KEYCODE_a + _fightCount)) {
+ msg.keycode < (int)(Common::KEYCODE_a + _remainingCount)) {
if (_option == OPTION_FIGHT)
fightMonster(msg.keycode - Common::KEYCODE_a);
else
@@ -363,29 +363,33 @@ void Combat::writeOptions() {
}
void Combat::writeAllOptions() {
- assert(g_globals->_currCharacter);
+ assert(g_globals->_currCharacter &&
+ g_globals->_currCharacter == g_globals->_combatParty[_currentChar]);
+ const Character &c = *g_globals->_currCharacter;
writeString(0, 20, STRING["dialogs.combat.options_for"]);
- writeString(0, 22, g_globals->_currCharacter->_name);
+ writeString(0, 22, c._name);
// Highlight the currently active character
writeChar(3 + 4 * (_currentChar % 2), 3 + (_currentChar / 2),
(unsigned char)'1' + _currentChar + 0x80);
- bool canAttack = g_globals->_combatParty[_currentChar]->_canAttack;
- if (canAttack) {
+ bool testShoot;
+ if (c._canAttack) {
writeAttackOptions();
_allowAttack = true;
_allowFight = true;
// Archers can always attack
- canAttack = g_globals->_currCharacter->_class == ARCHER;
+ testShoot = c._class == ARCHER;
+ } else {
+ testShoot = true;
}
- if (canAttack && g_globals->_currCharacter->_missileAttr) {
+ if (testShoot && c._missileAttr._base) {
_allowShoot = true;
writeShootOption();
}
- if (g_globals->_currCharacter->_sp._current) {
+ if (c._sp._current) {
writeCastOption();
_allowCast = true;
}
@@ -396,11 +400,11 @@ void Combat::writeAllOptions() {
void Combat::writeDelaySelect() {
resetBottom();
- writeString(0, 0, STRING["dialogs.combat.set_delay"]);
- writeString(0, 26, Common::String::format(
+ writeString(0, 20, STRING["dialogs.combat.set_delay"]);
+ writeString(0, 23, Common::String::format(
STRING["dialogs.combat.delay_currently"].c_str(),
g_globals->_delay));
- escToGoBack(0, 3);
+ escToGoBack(0, 23);
}
void Combat::writeExchangeSelect() {
@@ -412,19 +416,19 @@ void Combat::writeExchangeSelect() {
}
void Combat::writeFightSelect() {
- _fightCount = MIN(_attackerVal, (int)_remainingMonsters.size());
+ _remainingCount = MIN(_attackerVal, (int)_remainingMonsters.size());
- writeString(10, 0, Common::String::format(
- STRING["dialogs.combat.fight_which"].c_str(), '@' + _fightCount));
- escToGoBack(12, 3);
+ writeString(10, 20, Common::String::format(
+ STRING["dialogs.combat.fight_which"].c_str(), 'A' + _remainingCount - 1));
+ escToGoBack(12, 23);
}
void Combat::writeShootSelect() {
- _fightCount = MIN(_attackerVal, (int)_remainingMonsters.size());
+ _remainingCount = MIN(_attackerVal, (int)_remainingMonsters.size());
- writeString(10, 0, Common::String::format(
- STRING["dialogs.combat.shoot_which"].c_str(), '@' + _fightCount));
- escToGoBack(12, 3);
+ writeString(10, 20, Common::String::format(
+ STRING["dialogs.combat.shoot_which"].c_str(), 'A' + _remainingCount - 1));
+ escToGoBack(12, 23);
}
void Combat::writeAttackOptions() {
@@ -805,9 +809,10 @@ Common::String Combat::getAttackString() {
line1 += STRING["dialogs.combat.misses"];
} else {
line1 += STRING["dialogs.combat.hit"];
- line1 += ' ';
if (_numberOfTimes > 1) {
+ line1 += ' ';
+
if (_timesHit == 1) {
line1 += STRING["dialogs.combat.once"];
} else {
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index 6d61dbf628b..f58a4e101e5 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -32,7 +32,7 @@ namespace Views {
class Combat : public TextView, public Game::Combat {
private:
LineArray _monsterSpellLines;
- uint _fightCount = 0;
+ uint _remainingCount = 0;
InfoMessage _spellResult;
// Combat options that have sub-option selection
enum SelectedOption {
Commit: f1dd50436571c3fee3874be1dfcdf04c1ef642df
https://github.com/scummvm/scummvm/commit/f1dd50436571c3fee3874be1dfcdf04c1ef642df
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:51+01:00
Commit Message:
MM: MM1: In combat allow keypresses to abort delay timeout
Changed paths:
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 5c94917e4df..c7ea8706d0f 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -222,6 +222,9 @@ void Combat::timeout() {
}
bool Combat::msgKeypress(const KeypressMessage &msg) {
+ if (endDelay())
+ return true;
+
if (_mode == SELECT_OPTION && _option != OPTION_NONE) {
if (msg.keycode == Common::KEYCODE_ESCAPE) {
combatLoop();
@@ -266,6 +269,9 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
}
bool Combat::msgAction(const ActionMessage &msg) {
+ if (endDelay())
+ return true;
+
if (_mode != SELECT_OPTION || (_option != OPTION_NONE &&
_option != OPTION_EXCHANGE))
return false;
Commit: cf129a03a0e5fdd1507dc98ac0ad9a223b8df0cc
https://github.com/scummvm/scummvm/commit/cf129a03a0e5fdd1507dc98ac0ad9a223b8df0cc
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Fix monster action check in combatLoop
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 2abdeb96de7..6a5ceefefd4 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -293,13 +293,12 @@ void Combat::combatLoop(bool checkMonstersFirst) {
_monsterP = _remainingMonsters[i];
monsterIndexOf();
- if (_monsterP->_speed && _monsterP->_speed >= _handicap3
- && !_remainingMonsters[i]->_checked) {
- _remainingMonsters[i]->_checked = true;
+ if (_monsterP->_speed && _monsterP->_speed >= _handicap3 && !_monsterP->_checked) {
+ _monsterP->_checked = true;
- if (_remainingMonsters[i]->_status & (MONFLAG_ASLEEP | MONFLAG_HELD |
- MONFLAG_WEBBED | MONFLAG_PARALYZED)) {
- checkMonsterFlees();
+ if (!(_monsterP->_status & (MONFLAG_ASLEEP | MONFLAG_HELD |
+ MONFLAG_WEBBED | MONFLAG_PARALYZED))) {
+ monsterAction();
return;
}
}
@@ -583,7 +582,7 @@ void Combat::proc2() {
_val9 = (val != 100 && val <= threshold) ? 1 : 0;
}
-void Combat::checkMonsterFlees() {
+void Combat::monsterAction() {
Encounter &enc = g_globals->_encounters;
byte bitset = _monsterP->_field1e;
int threshold = -1;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 2e29877d486..e0216408e2b 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -201,7 +201,7 @@ protected:
/**
* Calculate a monster action
*/
- void checkMonsterFlees();
+ void monsterAction();
/**
* Check if monster is mindless and wandering
Commit: b07b05c47884193773f513de7ba11f9fd3beab6c
https://github.com/scummvm/scummvm/commit/b07b05c47884193773f513de7ba11f9fd3beab6c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Rename handicap fields
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 6a5ceefefd4..87bdd11dd05 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -28,6 +28,8 @@ namespace MM {
namespace MM1 {
namespace Game {
+#define STARTING_HANDICAP 40
+
Combat::Combat() : MonsterTouch() {
g_globals->_combat = this;
clear();
@@ -58,8 +60,8 @@ void Combat::clear() {
_numberOfTimes = 0;
_attackerLevel = 0;
_advanceIndex = 0;
- _handicap1 = _handicap2 = 0;
- _handicap3 = _handicap4 = 0;
+ _handicapThreshold = _handicapParty = 0;
+ _handicapMonsters = _handicapDelta = 0;
_handicap = HANDICAP_EVEN;
_monsterP = nullptr;
_monsterIndex = _currentChar = 0;
@@ -202,31 +204,31 @@ void Combat::checkRightWall() {
}
void Combat::setupHandicap() {
- _handicap2 = _handicap3 = 40;
- _handicap1 = getRandomNumber(7);
+ _handicapParty = _handicapMonsters = STARTING_HANDICAP;
+ _handicapThreshold = getRandomNumber(7);
int val = getRandomNumber(7);
- if (val < _handicap1) {
- SWAP(val, _handicap1);
- _handicap4 = val - _handicap1;
+ if (val < _handicapThreshold) {
+ SWAP(val, _handicapThreshold);
+ _handicapDelta = val - _handicapThreshold;
- if (_handicap4) {
+ if (_handicapDelta) {
_handicap = HANDICAP_MONSTER;
- _handicap2 += _handicap4;
+ _handicapParty += _handicapDelta;
return;
}
- } else if (val > _handicap1) {
- _handicap4 = val - _handicap1;
+ } else if (val > _handicapThreshold) {
+ _handicapDelta = val - _handicapThreshold;
- if (_handicap4) {
+ if (_handicapDelta) {
_handicap = HANDICAP_PARTY;
- _handicap3 += _handicap4;
+ _handicapMonsters += _handicapDelta;
return;
}
}
_handicap = HANDICAP_EVEN;
- _handicap4 = 0;
+ _handicapDelta = 0;
}
bool Combat::canMonsterCast() const {
@@ -275,7 +277,7 @@ void Combat::combatLoop(bool checkMonstersFirst) {
Character &c = *g_globals->_combatParty[i];
int speed = c._speed._current;
- if (speed && speed >= _handicap2 && !c._checked) {
+ if (speed && speed >= _handicapParty && !c._checked) {
_currentChar = i;
g_globals->_currCharacter = &c;
@@ -293,7 +295,7 @@ void Combat::combatLoop(bool checkMonstersFirst) {
_monsterP = _remainingMonsters[i];
monsterIndexOf();
- if (_monsterP->_speed && _monsterP->_speed >= _handicap3 && !_monsterP->_checked) {
+ if (_monsterP->_speed && _monsterP->_speed >= _handicapMonsters && !_monsterP->_checked) {
_monsterP->_checked = true;
if (!(_monsterP->_status & (MONFLAG_ASLEEP | MONFLAG_HELD |
@@ -305,17 +307,17 @@ void Combat::combatLoop(bool checkMonstersFirst) {
}
// Decrease the handicap/speed threshold
- if (_handicap2 == 1 && _handicap3 == 1) {
+ if (_handicapParty == 1 && _handicapMonsters == 1) {
// End of the round
nextRound();
break;
} else {
- if (_handicap2 != 1)
- --_handicap2;
- if (_handicap3 != 1)
- --_handicap3;
+ if (_handicapParty != 1)
+ --_handicapParty;
+ if (_handicapMonsters != 1)
+ --_handicapMonsters;
}
- assert(_handicap2 >= 1 && _handicap3 >= 1);
+ assert(_handicapParty >= 1 && _handicapMonsters >= 1);
}
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index e0216408e2b..1fc29dbd45d 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -51,8 +51,8 @@ protected:
int _numberOfTimes;
int _attackerLevel;
int _advanceIndex;
- int _handicap1, _handicap2;
- int _handicap3, _handicap4;
+ int _handicapThreshold, _handicapParty;
+ int _handicapMonsters, _handicapDelta;
int _attackerVal;
int _totalExperience;
Common::String _monsterName;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index c7ea8706d0f..ff2272074ed 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -480,11 +480,11 @@ void Combat::writeHandicap() {
break;
case HANDICAP_PARTY:
writeString(STRING["dialogs.combat.party_plus"]);
- writeNumber(_handicap4);
+ writeNumber(_handicapDelta);
break;
case HANDICAP_MONSTER:
writeString(STRING["dialogs.combat.monster_plus"]);
- writeNumber(_handicap4);
+ writeNumber(_handicapDelta);
break;
}
}
Commit: 5e976fd2ce9c96c1257e093b8c4fcfd1729b7639
https://github.com/scummvm/scummvm/commit/5e976fd2ce9c96c1257e093b8c4fcfd1729b7639
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Rename monster _field1E and enum
Changed paths:
engines/mm/mm1/data/monsters.cpp
engines/mm/mm1/data/monsters.h
engines/mm/mm1/game/combat.cpp
diff --git a/engines/mm/mm1/data/monsters.cpp b/engines/mm/mm1/data/monsters.cpp
index e46489d5379..60aa36e967a 100644
--- a/engines/mm/mm1/data/monsters.cpp
+++ b/engines/mm/mm1/data/monsters.cpp
@@ -56,7 +56,7 @@ bool Monsters::load() {
mon._bonusOnTouch = getNextValue(line);
mon._specialAbility = getNextValue(line);
mon._specialThreshold = getNextValue(line);
- mon._field1e = getNextValue(line);
+ mon._counterFlags = getNextValue(line);
mon._imgNum = getNextValue(line);
}
diff --git a/engines/mm/mm1/data/monsters.h b/engines/mm/mm1/data/monsters.h
index b9e52d955d6..1345d701b49 100644
--- a/engines/mm/mm1/data/monsters.h
+++ b/engines/mm/mm1/data/monsters.h
@@ -53,10 +53,10 @@ enum Fiedl1A {
FIELD1A_80 = 0x80
};
-enum Field1E {
- FIELD1E_F = 0xf,
- FIELD1E_10 = 0x10, FIELD1E_20 = 0x20,
- FIELD1E_40 = 0x40, FIELD1E_80 = 0x80
+enum MonsterCounter {
+ COUNTER_BITS = 0xf,
+ COUNTER_THRESHOLD1 = 0x10, COUNTER_THRESHOLD2 = 0x20,
+ COUNTER_REGENERATE = 0x40, COUNTER_ADVANCES = 0x80
};
struct Monster {
@@ -75,7 +75,7 @@ struct Monster {
byte _bonusOnTouch;
byte _specialAbility;
byte _specialThreshold;
- byte _field1e;
+ byte _counterFlags;
byte _imgNum;
// Runtime combat fields
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 87bdd11dd05..12be839e8d2 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -491,7 +491,7 @@ bool Combat::moveMonsters() {
_advanceIndex = i;
if (!(_remainingMonsters[i]->_status & ~MONFLAG_SILENCED) &&
- _remainingMonsters[i]->_field1e & FIELD1E_80) {
+ _remainingMonsters[i]->_counterFlags & COUNTER_ADVANCES) {
monsterAdvances();
hasAdvance = true;
}
@@ -517,7 +517,7 @@ bool Combat::monsterChanges() {
for (uint i = 0; i < _remainingMonsters.size(); ++i) {
monsterSetPtr(i);
- if ((_monsterP->_field1e & FIELD1E_40) &&
+ if ((_monsterP->_counterFlags & COUNTER_REGENERATE) &&
(_monsterP->_defaultHP != _remainingMonsters[i]->_hp)) {
_monstersRegenerate = true;
int newVal = _remainingMonsters[i]->_hp + 5;
@@ -586,14 +586,14 @@ void Combat::proc2() {
void Combat::monsterAction() {
Encounter &enc = g_globals->_encounters;
- byte bitset = _monsterP->_field1e;
+ byte bitset = _monsterP->_counterFlags;
int threshold = -1;
_activeMonsterNum = _monsterIndex;
_monsterName = _monsterP->_name;
monsterIndexOf();
- if (!(bitset & (FIELD1E_10 | FIELD1E_20))) {
+ if (!(bitset & (COUNTER_THRESHOLD1 | COUNTER_THRESHOLD2))) {
if (enc._highestLevel < 4) {
} else if (enc._highestLevel < 9) {
threshold = 50;
@@ -602,14 +602,14 @@ void Combat::monsterAction() {
} else {
threshold = 0;
}
- } else if (!(bitset & FIELD1E_10)) {
+ } else if (!(bitset & COUNTER_THRESHOLD1)) {
if (enc._highestLevel < 9) {
} else if (enc._highestLevel < 14) {
threshold = 50;
} else {
threshold = 75;
}
- } else if (!(bitset & FIELD1E_20)) {
+ } else if (!(bitset & COUNTER_THRESHOLD2)) {
if (enc._highestLevel < 14) {
} else {
threshold = 50;
@@ -642,10 +642,10 @@ bool Combat::checkMonsterSpells() {
if (!_monsterP->_specialAbility || (_monsterP->_specialAbility & 0x80) ||
(getRandomNumber(100) >= _monsterP->_specialThreshold) ||
- !(_monsterP->_field1e & 0xf))
+ !(_monsterP->_counterFlags & COUNTER_BITS))
return false;
- _monsterP->_field1e--;
+ _monsterP->_counterFlags--;
if (!_monsterP->_specialAbility || _monsterP->_specialAbility >= 33)
return false;
@@ -657,7 +657,7 @@ bool Combat::checkMonsterSpells() {
void Combat::checkMonsterActions() {
if (checkMonsterSpells())
- // Monster wandered or cast spell, so things are taken care of. Exit
+ // Monster wandered or cast spell, so things are taken care of
return;
_destCharCtr = 0;
@@ -666,12 +666,12 @@ void Combat::checkMonsterActions() {
return;
}
- if (!(_monsterP->_specialAbility & 0x80) || !(_monsterP->_field1e & FIELD1E_F)) {
+ if (!(_monsterP->_specialAbility & 0x80) || !(_monsterP->_counterFlags & COUNTER_BITS)) {
setMode(WAITS_FOR_OPENING);
return;
}
- _monsterP->_field1e--;
+ _monsterP->_counterFlags--;
// Pick a random character to shoot at
int charNum = getRandomNumber(g_globals->_party.size()) - 1;
Commit: 5e773537ebf2f7706725530512274c7b82068d53
https://github.com/scummvm/scummvm/commit/5e773537ebf2f7706725530512274c7b82068d53
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Fix cancelling combat spell and then re-casting
Changed paths:
engines/mm/mm1/views/spells/cast_spell.cpp
engines/mm/mm1/views/spells/cast_spell.h
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index af6d4bd576b..55ebb467607 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -58,6 +58,11 @@ bool CastSpell::msgValue(const ValueMessage &msg) {
return true;
}
+bool CastSpell::msgUnfocus(const UnfocusMessage &msg) {
+ _state = SELECT_SPELL;
+ return true;
+}
+
void CastSpell::setState(State state) {
_state = state;
diff --git a/engines/mm/mm1/views/spells/cast_spell.h b/engines/mm/mm1/views/spells/cast_spell.h
index c567a53d0c6..21275e20487 100644
--- a/engines/mm/mm1/views/spells/cast_spell.h
+++ b/engines/mm/mm1/views/spells/cast_spell.h
@@ -72,6 +72,7 @@ public:
}
bool msgValue(const ValueMessage &msg) override;
+ bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
Commit: b157a527d045ae7e87d34f2de8cb3f591c7e56ea
https://github.com/scummvm/scummvm/commit/b157a527d045ae7e87d34f2de8cb3f591c7e56ea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Fix enter to cast text
Changed paths:
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index ff2272074ed..75f65819a59 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -83,6 +83,10 @@ bool Combat::msgGame(const GameMessage &msg) {
return true;
} else if (msg._name == "SPELL_RESULT") {
+ InfoMessage infoMsg(20 - msg._stringValue.size() / 2, 21,
+ msg._stringValue);
+ infoMsg._delaySeconds = 3;
+
displaySpellResult(msg._stringValue);
return true;
}
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index 55ebb467607..1ab7a786b58 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -121,8 +121,7 @@ void CastSpell::draw() {
break;
case PRESS_ENTER:
- clearSurface();
- writeString(24, 3, STRING["dialogs.misc.enter_to_cast"]);
+ writeString(24, 4, STRING["spells.enter_to_cast"]);
break;
default:
@@ -222,14 +221,7 @@ void CastSpell::performSpell(Character *chr) {
void CastSpell::spellDone() {
Common::String msg = getSpellError();
int xp = 20 - (msg.size() / 2);
-/*
- switch (getSpellState()) {
- case Game::SS_NOT_ENOUGH_GEMS: xp = 9; break;
- case Game::SS_COMBAT_ONLY: xp = 10; break;
- case Game::SS_OUTDOORS_ONLY: xp = 10; break;
- default: break;
- }
- */
+
spellDone(msg, xp);
}
Commit: 9ede9e119f6453afc3f790b380f61ea798452816
https://github.com/scummvm/scummvm/commit/9ede9e119f6453afc3f790b380f61ea798452816
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Rendering of combat spell done
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/spell_casting.cpp
engines/mm/mm1/maps/maps.h
engines/mm/mm1/messages.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 12be839e8d2..a70a364f60a 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -232,7 +232,7 @@ void Combat::setupHandicap() {
}
bool Combat::canMonsterCast() const {
- return !(g_maps->_currentState & Maps::SFLAG_DISABLE_MONSTER_SPELLS) &&
+ return !(g_maps->_currentState & Maps::SFLAG_SPELLS_DISALLOWED) &&
!(g_globals->_encounters._monsterList[_monsterIndex]._status
& (MONFLAG_BLIND | MONFLAG_SILENCED));
}
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index ec213f90b2b..7d62de16ac2 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -131,7 +131,7 @@ bool SpellCasting::hasCharTarget() const {
}
bool SpellCasting::isMagicAllowed() const {
- return !(g_maps->_currentState & 2);
+ return !(g_maps->_currentState & Maps::SFLAG_SPELLS_DISALLOWED);
}
Common::String SpellCasting::getSpellError() const {
diff --git a/engines/mm/mm1/maps/maps.h b/engines/mm/mm1/maps/maps.h
index 00e90e8b50a..c964c304805 100644
--- a/engines/mm/mm1/maps/maps.h
+++ b/engines/mm/mm1/maps/maps.h
@@ -42,7 +42,7 @@ enum DirMask {
};
enum StateFlag {
- SFLAG_DISABLE_MONSTER_SPELLS = 2
+ SFLAG_SPELLS_DISALLOWED = 2
};
enum Visited {
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index d25e4372dac..f5a5a42fa40 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -82,7 +82,7 @@ struct GameMessage : public Message {
GameMessage(const Common::String &name, int value) : Message(),
_name(name), _value(value) {}
GameMessage(const Common::String &name, const Common::String &value) :
- Message(), _name(name), _stringValue(value) {}
+ Message(), _name(name), _stringValue(value), _value(-1) {}
};
struct HeaderMessage : public Message {
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 75f65819a59..4479294b2dd 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -83,11 +83,12 @@ bool Combat::msgGame(const GameMessage &msg) {
return true;
} else if (msg._name == "SPELL_RESULT") {
- InfoMessage infoMsg(20 - msg._stringValue.size() / 2, 21,
- msg._stringValue);
- infoMsg._delaySeconds = 3;
+ assert(msg._value >= 0 && msg._value < 40);
+ _spellResult._lines.clear();
+ _spellResult._lines.push_back(Line(msg._value, 1, msg._stringValue));
+ _spellResult._delaySeconds = 3;
- displaySpellResult(msg._stringValue);
+ setMode(SPELL_RESULT);
return true;
}
@@ -218,7 +219,11 @@ void Combat::timeout() {
break;
}
case SPELL_RESULT:
- _spellResult._timeoutCallback();
+ if (_spellResult._timeoutCallback)
+ _spellResult._timeoutCallback();
+ else
+ // Character is done
+ block();
break;
default:
break;
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index 1ab7a786b58..2a9be56b304 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -228,7 +228,10 @@ void CastSpell::spellDone() {
void CastSpell::spellDone(const Common::String &msg, int xp) {
if (isInCombat()) {
close();
- g_events->focusedView()->send(GameMessage("SPELL_RESULT", msg));
+
+ GameMessage gameMsg("SPELL_RESULT", msg);
+ gameMsg._value = xp;
+ g_events->focusedView()->send(gameMsg);
} else {
_state = ENDING;
Commit: 50a4e236ad212cb9ff38750dbf10824bb83415e8
https://github.com/scummvm/scummvm/commit/50a4e236ad212cb9ff38750dbf10824bb83415e8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Fix showing non-combat spell only message
Changed paths:
engines/mm/mm1/views/spells/cast_spell.cpp
diff --git a/engines/mm/mm1/views/spells/cast_spell.cpp b/engines/mm/mm1/views/spells/cast_spell.cpp
index 2a9be56b304..6a3ffeea0e3 100644
--- a/engines/mm/mm1/views/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views/spells/cast_spell.cpp
@@ -148,14 +148,16 @@ void CastSpell::spellNumberEntered(uint num) {
}
setSpell(g_globals->_currCharacter, _spellLevel, num);
- if (!canCast())
+ if (!canCast()) {
spellDone();
- else if (hasCharTarget())
- setState(SELECT_CHAR);
- else
- setState(PRESS_ENTER);
+ } else {
+ if (hasCharTarget())
+ setState(SELECT_CHAR);
+ else
+ setState(PRESS_ENTER);
- draw();
+ draw();
+ }
}
bool CastSpell::msgKeypress(const KeypressMessage &msg) {
Commit: ce27924bc3452e53b791e04103def0278ff32ddf
https://github.com/scummvm/scummvm/commit/ce27924bc3452e53b791e04103def0278ff32ddf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:52+01:00
Commit Message:
MM: MM1: Fix monster flees/wander rendering
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index bac93d25e74..69efb0b4a78 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -373,6 +373,7 @@ dialogs:
regenerate: "SOME MONSTERS REGENERATE!"
overcome: "SOME MONSTERS OVERCOME SPELLS!"
monster_flees: "RUNS AWAY..."
+ monster_wanders: "WANDERS AIMLESSLY"
attacks: "ATTACKS"
shoots: "SHOOTS"
weapon_no_effect: "WEAPON HAS NO EFFECT!"
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 4479294b2dd..3c01912e1d3 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -116,7 +116,7 @@ void Combat::draw() {
return;
case MONSTER_FLEES:
case MONSTER_WANDERS:
- writeMonsterAction();
+ writeMonsterAction(_mode == MONSTER_FLEES);
delaySeconds(3);
return;
case MONSTER_SPELL:
@@ -622,11 +622,12 @@ void Combat::writeMonsterEffects() {
writeMonsters();
}
-void Combat::writeMonsterAction() {
- writeChar(12, _monsterIndex, 0xC1);
+void Combat::writeMonsterAction(bool flees) {
resetBottom();
writeString(0, 20, _monsterName);
- writeString(STRING["dialogs.combat.monster_flees"]);
+ writeString(STRING[flees ?
+ "dialogs.combat.monster_flees" : "dialogs.combat.monster_wanders"
+ ]);
}
void Combat::writeMonsterSpell() {
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index f58a4e101e5..c80cd23d3f6 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -117,7 +117,7 @@ private:
/**
* Handles a monster action
*/
- void writeMonsterAction();
+ void writeMonsterAction(bool flees);
/**
* Write out message from a monster casting a spell
Commit: f24cfbb048ca0c07d0d39dbce0ac6fcb6d9c6e98
https://github.com/scummvm/scummvm/commit/f24cfbb048ca0c07d0d39dbce0ac6fcb6d9c6e98
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:53+01:00
Commit Message:
MM: MM1: Add monster count parameter to encounter console cmd
Changed paths:
engines/mm/mm1/console.cpp
diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 6653fd87579..52b50462905 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -328,7 +328,7 @@ bool Console::cmdCast(int argc, const char **argv) {
bool Console::cmdEncounter(int argc, const char **argv) {
if (argc < 2) {
- debugPrintf("encounter <monster-num> [<level>, <encounter type>]\n");
+ debugPrintf("encounter <monster-num> [<level>, <# monsters>, <encounter type>]\n");
return true;
} else {
@@ -342,13 +342,15 @@ bool Console::cmdEncounter(int argc, const char **argv) {
if (level < 1 || level >= 15)
level = 1;
- int encType = (argc > 3) ? strToInt(argv[2]) :
+ int count = (argc > 3) ? strToInt(argv[3]) : 1;
+ int encType = (argc > 4) ? strToInt(argv[2]) :
Game::NORMAL_ENCOUNTER;
if (encType != -1 || encType == 0 || encType == 1)
enc._encounterType = (Game::EncounterType)encType;
enc.clearMonsters();
- enc.addMonster(monsterNum, level);
+ for (int i = 0; i < count; ++i)
+ enc.addMonster(monsterNum, level);
enc._manual = true;
enc._levelIndex = 80;
Commit: 545ae551fd4cf355908a50b64e219aa2c39a3b3e
https://github.com/scummvm/scummvm/commit/545ae551fd4cf355908a50b64e219aa2c39a3b3e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:53+01:00
Commit Message:
MM: MM1: Clarify the variables for frontline monster attacker count
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
engines/mm/mm1/views/combat.h
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index a70a364f60a..b295850f2f3 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -65,7 +65,7 @@ void Combat::clear() {
_handicap = HANDICAP_EVEN;
_monsterP = nullptr;
_monsterIndex = _currentChar = 0;
- _attackerVal = 0;
+ _attackersCount = 0;
_totalExperience = 0;
_advanceIndex = 0;
_monstersResistSpells = _monstersRegenerate = false;
@@ -180,13 +180,13 @@ void Combat::setupCanAttacks() {
}
void Combat::setupAttackerVal() {
- _attackerVal = 0;
+ _attackersCount = 0;
for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
if (g_globals->_combatParty[i]->_canAttack)
- ++_attackerVal;
+ ++_attackersCount;
}
- _attackerVal = getRandomNumber(_attackerVal + 1) - 1;
+ _attackersCount = getRandomNumber(_attackersCount + 1) - 1;
}
void Combat::checkLeftWall() {
@@ -483,7 +483,7 @@ void Combat::updateHighestLevel() {
}
bool Combat::moveMonsters() {
- if (_attackerVal >= (int)_remainingMonsters.size())
+ if (_attackersCount >= (int)_remainingMonsters.size())
return false;
bool hasAdvance = false;
@@ -661,7 +661,7 @@ void Combat::checkMonsterActions() {
return;
_destCharCtr = 0;
- if (_activeMonsterNum < _attackerVal) {
+ if (_activeMonsterNum < _attackersCount) {
selectMonsterTarget();
return;
}
@@ -1146,7 +1146,7 @@ void Combat::destroyMonster() {
void Combat::summonLightning() {
SpellsState &ss = g_globals->_spellsState;
- if (_destMonsterNum < _attackerVal) {
+ if (_destMonsterNum < _attackersCount) {
Common::String line1 = Common::String::format("|%s| %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
@@ -1202,7 +1202,7 @@ void Combat::paralyze() {
ss._mmVal1++;
ss._mmVal2 = 6;
- ss._resistanceType = _attackerVal;
+ ss._resistanceType = _attackersCount;
ss._newCondition = BAD_CONDITION;
iterateMonsters1();
@@ -1304,7 +1304,7 @@ void Combat::identifyMonster() {
void Combat::fireball() {
SpellsState &ss = g_globals->_spellsState;
- if (_destMonsterNum < _attackerVal) {
+ if (_destMonsterNum < _attackersCount) {
Common::String line1 = Common::String::format("|%s| %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
@@ -1363,7 +1363,7 @@ void Combat::weaken() {
bool Combat::web() {
SpellsState &ss = g_globals->_spellsState;
- if (_destMonsterNum < _attackerVal)
+ if (_destMonsterNum < _attackersCount)
return false;
ss._mmVal1++;
@@ -1377,10 +1377,10 @@ bool Combat::web() {
bool Combat::acidRain() {
SpellsState &ss = g_globals->_spellsState;
- if (_attackerVal >= (int)_remainingMonsters.size())
+ if (_attackersCount >= (int)_remainingMonsters.size())
return false;
- _destMonsterNum = _attackerVal;
+ _destMonsterNum = _attackersCount;
monsterSetPtr(_destMonsterNum);
monsterIndexOf();
@@ -1542,7 +1542,7 @@ void Combat::selectMonsterTarget() {
// means enabling the whole party to be able to attack directly
for (uint i = 0; i < g_globals->_combatParty.size(); ++i)
g_globals->_combatParty[i]->_canAttack = true;
- _attackerVal = g_globals->_party.size() * 2;
+ _attackersCount = g_globals->_party.size() * 2;
setMode(INFILTRATION);
}
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 1fc29dbd45d..6cd5d9cbdd9 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -53,7 +53,7 @@ protected:
int _advanceIndex;
int _handicapThreshold, _handicapParty;
int _handicapMonsters, _handicapDelta;
- int _attackerVal;
+ int _attackersCount;
int _totalExperience;
Common::String _monsterName;
bool _monstersResistSpells;
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 3c01912e1d3..7bb08039391 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -244,7 +244,7 @@ bool Combat::msgKeypress(const KeypressMessage &msg) {
case OPTION_FIGHT:
case OPTION_SHOOT:
if (msg.keycode >= Common::KEYCODE_a &&
- msg.keycode < (int)(Common::KEYCODE_a + _remainingCount)) {
+ msg.keycode < (int)(Common::KEYCODE_a + _attackableCount)) {
if (_option == OPTION_FIGHT)
fightMonster(msg.keycode - Common::KEYCODE_a);
else
@@ -431,18 +431,18 @@ void Combat::writeExchangeSelect() {
}
void Combat::writeFightSelect() {
- _remainingCount = MIN(_attackerVal, (int)_remainingMonsters.size());
+ _attackableCount = MIN(_attackersCount, (int)_remainingMonsters.size());
writeString(10, 20, Common::String::format(
- STRING["dialogs.combat.fight_which"].c_str(), 'A' + _remainingCount - 1));
+ STRING["dialogs.combat.fight_which"].c_str(), 'A' + _attackableCount - 1));
escToGoBack(12, 23);
}
void Combat::writeShootSelect() {
- _remainingCount = MIN(_attackerVal, (int)_remainingMonsters.size());
+ _attackableCount = MIN(_attackersCount, (int)_remainingMonsters.size());
writeString(10, 20, Common::String::format(
- STRING["dialogs.combat.shoot_which"].c_str(), 'A' + _remainingCount - 1));
+ STRING["dialogs.combat.shoot_which"].c_str(), 'A' + _attackableCount - 1));
escToGoBack(12, 23);
}
@@ -517,7 +517,7 @@ void Combat::writeMonsters() {
} else {
for (int i = 0; i < (int)_remainingMonsters.size(); ++i) {
_textPos = Common::Point(11, i);
- writeChar(i < _attackerVal ? '+' : ' ');
+ writeChar(i < _attackersCount ? '+' : ' ');
unsigned char c = 'A' + i;
if ((i == _activeMonsterNum) && (_mode == MONSTER_ADVANCES ||
_mode == MONSTER_ATTACK || _mode == MONSTER_SPELL))
diff --git a/engines/mm/mm1/views/combat.h b/engines/mm/mm1/views/combat.h
index c80cd23d3f6..5038d5082bb 100644
--- a/engines/mm/mm1/views/combat.h
+++ b/engines/mm/mm1/views/combat.h
@@ -32,7 +32,7 @@ namespace Views {
class Combat : public TextView, public Game::Combat {
private:
LineArray _monsterSpellLines;
- uint _remainingCount = 0;
+ uint _attackableCount = 0;
InfoMessage _spellResult;
// Combat options that have sub-option selection
enum SelectedOption {
Commit: d49165fa5287724f6db0cdc13702b7297b7e7995
https://github.com/scummvm/scummvm/commit/d49165fa5287724f6db0cdc13702b7297b7e7995
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:53+01:00
Commit Message:
MM: MM1: Code for removing dead monsters
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/game/combat.h
engines/mm/mm1/views/combat.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index b295850f2f3..71a5df2ed06 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -712,6 +712,13 @@ void Combat::removeMonster() {
} while (changed);
}
+void Combat::removeDeadMonsters() {
+ for (int i = (int)_remainingMonsters.size() - 1; i >= 0; --i) {
+ if (_remainingMonsters[i]->_status == MONFLAG_DEAD)
+ _remainingMonsters.remove_at(i);
+ }
+}
+
void Combat::checkParty() {
_val10 = 0;
diff --git a/engines/mm/mm1/game/combat.h b/engines/mm/mm1/game/combat.h
index 6cd5d9cbdd9..c9075d4318c 100644
--- a/engines/mm/mm1/game/combat.h
+++ b/engines/mm/mm1/game/combat.h
@@ -293,6 +293,11 @@ protected:
*/
void retreat();
+ /**
+ * Called to remove any dead monsters
+ */
+ void removeDeadMonsters();
+
private:
void spellFailed();
void destroyMonster();
diff --git a/engines/mm/mm1/views/combat.cpp b/engines/mm/mm1/views/combat.cpp
index 7bb08039391..3907620b21f 100644
--- a/engines/mm/mm1/views/combat.cpp
+++ b/engines/mm/mm1/views/combat.cpp
@@ -189,9 +189,11 @@ void Combat::timeout() {
case MONSTERS_AFFECTED:
case CHAR_ATTACKS:
case NO_EFFECT:
+ removeDeadMonsters();
combatLoop();
break;
case MONSTER_FLEES:
+ removeDeadMonsters();
checkMonsterSpells();
break;
case MONSTER_WANDERS:
Commit: 6d5066745528f6e23f583a818bf20ccbc1550ad6
https://github.com/scummvm/scummvm/commit/6d5066745528f6e23f583a818bf20ccbc1550ad6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:53+01:00
Commit Message:
MM: XEEN: Properly fix Swords monster list
Changed paths:
devtools/create_mm/create_xeen/str.cpp
devtools/create_mm/create_xeen/swords.cpp
devtools/create_mm/files/xeen/monsters.swd
engines/mm/xeen/map.cpp
diff --git a/devtools/create_mm/create_xeen/str.cpp b/devtools/create_mm/create_xeen/str.cpp
index 26a3f16ef66..bc9a9f1763e 100644
--- a/devtools/create_mm/create_xeen/str.cpp
+++ b/devtools/create_mm/create_xeen/str.cpp
@@ -1,3 +1,3 @@
#define SCUMMVM_UTIL
-#include "../../../common/base-str.cpp"
+#include "../../../common/str-base.cpp"
#include "../../../common/str.cpp"
diff --git a/devtools/create_mm/create_xeen/swords.cpp b/devtools/create_mm/create_xeen/swords.cpp
index 337434d92ea..d332c4c0541 100644
--- a/devtools/create_mm/create_xeen/swords.cpp
+++ b/devtools/create_mm/create_xeen/swords.cpp
@@ -25,14 +25,14 @@
#include "file.h"
#include "swords.h"
-#define MONSTERS_COUNT 150
+#define MONSTERS_COUNT 151
extern void NORETURN_PRE error(const char *s, ...);
void writeSwordsData(const char *swordsDatName) {
Common::File f;
Common::MemFile monsters;
- const int size = MONSTERS_COUNT * 61;
+ const int size = MONSTERS_COUNT * 60;
const int32 offset = 0x44200;
byte buffer[size];
diff --git a/devtools/create_mm/files/xeen/monsters.swd b/devtools/create_mm/files/xeen/monsters.swd
index 42070641084..9a4cadf6921 100644
Binary files a/devtools/create_mm/files/xeen/monsters.swd and b/devtools/create_mm/files/xeen/monsters.swd differ
diff --git a/engines/mm/xeen/map.cpp b/engines/mm/xeen/map.cpp
index 60bc67c7533..b233ff565ee 100644
--- a/engines/mm/xeen/map.cpp
+++ b/engines/mm/xeen/map.cpp
@@ -695,42 +695,6 @@ void Map::load(int mapId) {
_animationInfo.load("dark.dat");
_monsterData.load((_vm->getGameID() == GType_Swords) ? "monsters.swd" : "dark.mon");
_wallPicSprites.load("darkpic.dat");
-
- // FIXME: Temporary fix for last monster in code to avoid regenerating xeen.ccs
- if (_vm->getGameID() == GType_Swords) {
- MonsterStruct &m = _monsterData[150];
- m._name = "GateMaster";
- m._experience = 200000;
- m._hp = 1900;
- m._armorClass = 0x32;
- m._speed = 0x42;
- m._numberOfAttacks = 1;
- m._hatesClass = (CharacterClass)0xf;
- m._strikes = 15;
- m._dmgPerStrike = 0x82;
- m._attackType = (DamageType)4;
- m._specialAttack = (SpecialAttack)0x14;
- m._hitChance = 0;
- m._rangeAttack = 1;
- m._monsterType = (MonsterType)0;
- m._fireResistence = 100;
- m._electricityResistence = 40;
- m._coldResistence = 40;
- m._poisonResistence = 40;
- m._energyResistence = 40;
- m._magicResistence = 40;
- m._phsyicalResistence = 30;
- m._field29 = 0;
- m._gold = 0;
- m._gems = 0;
- m._itemDrop = 0;
- m._flying = 1;
- m._imageNumber = 31;
- m._loopAnimation = 0;
- m._animationEffect = 0;
- m._fx = 100;
- }
-
} else if (_vm->getGameID() == GType_Clouds) {
_animationInfo.load("animinfo.cld");
_monsterData.load("monsters.cld");
Commit: 62dd9be37ffb80d7d83741ae4d928bf12c21a7da
https://github.com/scummvm/scummvm/commit/62dd9be37ffb80d7d83741ae4d928bf12c21a7da
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-01-22T20:07:53+01:00
Commit Message:
MM: MM1: Fix gcc warnings
Changed paths:
engines/mm/mm1/game/combat.cpp
engines/mm/mm1/maps/map_town.cpp
diff --git a/engines/mm/mm1/game/combat.cpp b/engines/mm/mm1/game/combat.cpp
index 71a5df2ed06..8f1b296a5d2 100644
--- a/engines/mm/mm1/game/combat.cpp
+++ b/engines/mm/mm1/game/combat.cpp
@@ -988,7 +988,7 @@ void Combat::iterateMonsters1Inner() {
isEnd = true;
}
if (!isEnd)
- isEnd = ((int)_remainingMonsters.size() + _destMonsterNum - _spellMonsterCount) < 0;
+ isEnd = (int)((int)_remainingMonsters.size() + _destMonsterNum - _spellMonsterCount) < 0;
if (!isEnd) {
// Move to next iteration after display timeout
@@ -1072,7 +1072,7 @@ void Combat::iterateMonsters2Inner() {
isEnd = true;
}
if (!isEnd)
- isEnd = ((int)_remainingMonsters.size() + _destMonsterNum - _spellMonsterCount) < 0;
+ isEnd = (int)((int)_remainingMonsters.size() + _destMonsterNum - _spellMonsterCount) < 0;
if (!isEnd) {
// Move to next iteration after display timeout
@@ -1222,7 +1222,7 @@ bool Combat::divineIntervention() {
_divineInterventionUsed = true;
int age = (int)c._level + 5;
- if (c._level > 255)
+ if (age > 255)
return false;
c._age = age;
@@ -1404,7 +1404,7 @@ bool Combat::acidRain() {
}
void Combat::fingerOfDeath() {
- Common::String line1 = Common::String::format("|%s| %s",
+ Common::String line1 = Common::String::format("%s %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
@@ -1420,7 +1420,8 @@ void Combat::fingerOfDeath() {
}
removeMonster();
- Common::String line2 = Common::String::format("|%s| %s",
+ Common::String line2 = Common::String::format("%s %s",
+ monsterName.c_str(),
kills ? STRING["spells.char_effects.7"].c_str() :
STRING["monster_spells.not_affected"].c_str()
);
@@ -1435,7 +1436,7 @@ void Combat::fingerOfDeath() {
}
void Combat::disintegration() {
- Common::String line1 = Common::String::format("|%s| %s",
+ Common::String line1 = Common::String::format("%s %s",
g_globals->_currCharacter->_name,
STRING["spells.casts_spell"].c_str());
@@ -1450,7 +1451,8 @@ void Combat::disintegration() {
}
removeMonster();
- Common::String line2 = Common::String::format("|%s| %s",
+ Common::String line2 = Common::String::format("%s %s",
+ monsterName.c_str(),
kills ? STRING["spells.char_effects.disintegrated"].c_str() :
STRING["monster_spells.not_affected"].c_str()
);
diff --git a/engines/mm/mm1/maps/map_town.cpp b/engines/mm/mm1/maps/map_town.cpp
index 4b49a87663e..1cb9c7c5079 100644
--- a/engines/mm/mm1/maps/map_town.cpp
+++ b/engines/mm/mm1/maps/map_town.cpp
@@ -66,7 +66,7 @@ void MapTown::tavern() {
visitedBusiness();
send(SoundMessage(
- STRING[Common::String::format("maps.tavern_inside", _mapIndex)],
+ STRING["maps.tavern_inside"],
[]() {
g_events->addView("Tavern");
}
Commit: 316b65876a0b00a93095e1dfd0fd807b05be56bf
https://github.com/scummvm/scummvm/commit/316b65876a0b00a93095e1dfd0fd807b05be56bf
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-01-22T20:07:53+01:00
Commit Message:
MM: MM1: Add missing override keywords
Changed paths:
engines/mm/mm1/gfx/screen_decoder.h
engines/mm/mm1/views/create_characters.h
engines/mm/mm1/views/text_view.h
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
index bff229056dd..09b76099eec 100644
--- a/engines/mm/mm1/gfx/screen_decoder.h
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -42,7 +42,7 @@ public:
bool loadFile(const Common::String &fname,
int16 w = 320, int16 h = 200);
bool loadStream(Common::SeekableReadStream &stream, int16 w, int16 h);
- bool loadStream(Common::SeekableReadStream &stream) {
+ bool loadStream(Common::SeekableReadStream &stream) override {
return loadStream(stream, 320, 200);
}
diff --git a/engines/mm/mm1/views/create_characters.h b/engines/mm/mm1/views/create_characters.h
index 7f3d000cc47..4e17964d42e 100644
--- a/engines/mm/mm1/views/create_characters.h
+++ b/engines/mm/mm1/views/create_characters.h
@@ -96,7 +96,7 @@ public:
CreateCharacters() : TextView("CreateCharacters") {}
virtual ~CreateCharacters() {}
- bool msgFocus(const FocusMessage &msg) {
+ bool msgFocus(const FocusMessage &msg) override {
_newChar.reroll();
return true;
}
diff --git a/engines/mm/mm1/views/text_view.h b/engines/mm/mm1/views/text_view.h
index 2fa46d93d75..0e59d8a05e9 100644
--- a/engines/mm/mm1/views/text_view.h
+++ b/engines/mm/mm1/views/text_view.h
@@ -95,7 +95,7 @@ protected:
/**
* Called when an active timeout countdown expired
*/
- virtual void timeout();
+ virtual void timeout() override;
void drawGraphic(int gfxNum);
Commit: b6ee619b9ac153ec6f21540375386e09ef66486b
https://github.com/scummvm/scummvm/commit/b6ee619b9ac153ec6f21540375386e09ef66486b
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-01-22T20:07:53+01:00
Commit Message:
DISTS: Add placeholder for mm.dat file
Changed paths:
A dists/engine-data/mm.dat
diff --git a/dists/engine-data/mm.dat b/dists/engine-data/mm.dat
new file mode 100644
index 00000000000..e69de29bb2d
More information about the Scummvm-git-logs
mailing list