File: _metal_gear_overlay.tcl

package info (click to toggle)
openmsx 20.0%2Bdfsg-1.2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 27,544 kB
  • sloc: cpp: 236,922; xml: 49,948; tcl: 15,056; python: 5,385; perl: 281; sh: 77; makefile: 53
file content (183 lines) | stat: -rw-r--r-- 6,207 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# This script is based on:
# openMSX metal gear overlay script 2014/12/07
# By Dunnius / Bifi / Vampier 

namespace eval metal_gear_overlay {

variable num_enemies 11
variable max_hp
variable punch_max_hp
variable currentfield
# the map feature is disabled here in code, because it isn't very useful yet
variable map_feature_enabled false
variable metal_gear_overlay_active false

variable enemy_names [list \
	"" "01" "Bridge Segment" "Ellen Screaming 'help me'" "Soldier - Pattern 1" \
	"Soldier - Pattern 2" "Camera" "Landmine" "Gas cloud" "Enemy - Tank" \
	"Soldier - (Alert)" "Soldier - Red (Alert)" "Tank Shell" \
	"Soldier - Shooting" "Soldier - Guard" "Roller" "Trap Floor" "Metal Gear" \
	"Enemy - Bulldozer" "Soldier - Truck" "Soldier - Flying" \
	"Soldier - Fly to the Switch" "Soldier - Flying (Alert)" "Unknown3" \
	"Soldier - Run to the Switch" "Guard Dog" "Mr. Arnold" "Basement Guard Dogs" \
	"Soldier - Guard to building 3" "Event - Dogs will appear" "Soldier - Pattern 3" \
	"Scorpion" "Big Boss" "Shoot Gunner" "Machine Gun Kid" "Laser fence" \
	"Fire Trooper" "Fire ball" "Hind-D" "Event - Incoming tank shells" \
	"Event - Guards will switch shifts" "Coward Duck" "Unknown8" \
	"Shoot Gunner - Bullet" "Power Switch" "Event - Snake Gets Captured" \
	"Event - Access to building 2" "Bullet 1" "Soldier - Stationary Guard" \
	"POW" "Ellen" "Grey Fox" "Dr. Petrovich" "Laser Camera" "36" "Fake Dr. Petrovich" \
	"Unknown9" "Soldier - Silencer Guards" "Unknown11" "Bullet 2" \
	"Machine Gun Kid - Bullet" "Bullet 3" "Tank - Bullet" "Boomerang" "Zzz" \
	"Unknown13" "Unknown14" "Unknown15" "44" "45" "46" "47" "48" "49" "4A" \
	"4B" "4C" "4D" "4E" "4F" "50" "51" "52" "53" "54" "55" "56" "57" "58" \
	"59" "5A" "5B" "5C" "5D" "5E" "5F" "60" "61" "62" "63" "64" "65" "66" ]

set_help_text toggle_metal_gear_overlay \
"Shows OSD widgets that help you play Metal Gear. Only useful if you
are actually running this game... If you are not, you may get a lot of weird
stuff on your screen :) It mostly shows Snake and enemy properties on screen
and events that will happen."

proc init {} {
	variable num_enemies
	variable max_hp
	variable punch_max_hp
	variable currentfield
	variable map_feature_enabled

	# Create OSD elements
	osd_widgets::msx_init metal_gear

	for {set i 0} {$i < $num_enemies} {incr i} {
		osd_widgets::create_power_bar metal_gear.powerbar$i 16 2 0xff0080b0 0x00000080 0xffffffC0
		osd_widgets::create_power_bar metal_gear.punchbar$i 16 2 0x0080ffb0 0x00000080 0xffffffC0
		set max_hp($i) 0
		set punch_max_hp($i) 0
	}

	osd_widgets::create_power_bar metal_gear.powerbarsnake 24 2 0x00ff00b0 0x00000080 0xffffffC0
	osd_widgets::create_power_bar metal_gear.boss  24 8 0x00ff00b0 0x00000080 0xffffffC0

	set currentfield 0
	
	if {$map_feature_enabled} {
		for {set y 0} {$y < 16} {incr y} {
			for {set x 0} {$x < 16} {incr x} {
				set field [expr {$x + ($y * 16)}]
				osd create rectangle metal_gear.field$field -x [expr {($x * 3) + 1}] -y [expr {($y * 3) + 1}] -relw 2 -relh 2 -rgba 0x0000ff80
			}
		}
	}

	# Start the overlay refresh
	update_overlay
}

proc update_impl {} {
	variable max_hp
	variable punch_max_hp
	variable num_enemies
	variable enemy_names
	variable currentfield
	variable map_feature_enabled

	# check for field change
	set newfield [peek 0xC130]
	if {$currentfield != $newfield} {
		set previousfield $currentfield
		set currentfield $newfield

		# clear out old HP values if field has changed
		for {set i 0} {$i < $num_enemies} {incr i} {
			set punch_max_hp($i) 0
			set max_hp($i) 0
		}
		if {$map_feature_enabled} {
			osd configure metal_gear.field$previousfield -rgba 0x00ff0080
			osd configure metal_gear.field$currentfield -rgba 0xffffff80
		}
	}

	for {set i 0; set addr 0xD000} {$i < $num_enemies} {incr i; incr addr 0x80} {
		set enemy_type [peek $addr]
		set enemy_hp [peek [expr {$addr + 0x0D}]]
		if {$enemy_type > 0 && $enemy_hp > 0} {
			set pos_x [peek [expr {$addr + 5}]]
			set pos_y [peek [expr {$addr + 3}]]

			if {$enemy_hp > $max_hp($i)} {
				set max_hp($i) $enemy_hp
			}
			set power [expr {1.00 * $enemy_hp / $max_hp($i)}]
			set text "HP: $enemy_hp $i [lindex $enemy_names $enemy_type] - #$enemy_type"
			osd_widgets::update_power_bar metal_gear.powerbar$i $pos_x $pos_y $power $text
								
			# only show the punch bar when the enemy can be punched
			set enemy_punch_hp [expr {3 - [peek [expr {$addr + 0x7A}]]}]
			if {$enemy_punch_hp > 0} {
				if {$enemy_punch_hp > $punch_max_hp($i)} {
					set punch_max_hp($i) $enemy_punch_hp
				}
				set punch_power [expr {1.00 * $enemy_punch_hp / $punch_max_hp($i)}]
				osd_widgets::update_power_bar metal_gear.punchbar$i $pos_x [expr {$pos_y + 5}] $punch_power ""
			} else {
				osd_widgets::update_power_bar metal_gear.punchbar$i -50 -50 0 ""
			}
		} else {
			osd_widgets::update_power_bar metal_gear.powerbar$i -50 -50 0 ""
			osd_widgets::update_power_bar metal_gear.punchbar$i -50 -50 0 ""
		}
        }

	# get stats for snake
	set snake_hp [peek 0xC131]
	set power [expr {$snake_hp / 48.0}]
	set poisoned [peek 0xC139]
	set pos_x [peek 0xC184]
	set pos_y [peek 0xc182]

	set text ""
	if {$poisoned == 1} {
		set power 0
		set text "POISONED "
	}
	append text "($pos_x,$pos_y)  HP: $snake_hp"

	osd_widgets::update_power_bar metal_gear.powerbarsnake [expr {$pos_x - 13}] [expr {$pos_y + 20}] $power $text
}

proc update_overlay {} {
	variable metal_gear_overlay_active
	if {!$metal_gear_overlay_active} return

	# check if not in demo or weapon/item screen
	set c012 [peek 0xC012]
	if {$c012 == 0x00 || $c012 == 0x47 || $c012 == 0x50 || [peek 0xC151] != 0} {
		osd configure metal_gear -y 999
	} else {
		osd configure metal_gear -y 0
		update_impl
	}
	after frame [namespace code update_overlay]
}

proc toggle_metal_gear_overlay {} {
	variable metal_gear_overlay_active
	set metal_gear_overlay_active [expr {!$metal_gear_overlay_active}]
	if {$metal_gear_overlay_active} {
		init
		set text "Metal Gear overlay activated!"
	} else {
		osd destroy metal_gear
		set text "Metal Gear overlay deactivated."
	}
	message $text info
	return $text
}

namespace export toggle_metal_gear_overlay

};# namespace metal_gear_overlay

namespace import metal_gear_overlay::*