_metal_gear_overlay.tcl 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. # This script is based on:
  2. # openMSX metal gear overlay script 2014/12/07
  3. # By Dunnius / Bifi / Vampier
  4. namespace eval metal_gear_overlay {
  5. variable num_enemies 11
  6. variable max_hp
  7. variable punch_max_hp
  8. variable currentfield
  9. # the map feature is disabled here in code, because it isn't very useful yet
  10. variable map_feature_enabled false
  11. variable metal_gear_overlay_active false
  12. variable enemy_names [list \
  13. "" "01" "Bridge Segment" "Ellen Screaming 'help me'" "Soldier - Pattern 1" \
  14. "Soldier - Pattern 2" "Camera" "Landmine" "Gas cloud" "Enemy - Tank" \
  15. "Soldier - (Alert)" "Soldier - Red (Alert)" "Tank Shell" \
  16. "Soldier - Shooting" "Soldier - Guard" "Roller" "Trap Floor" "Metal Gear" \
  17. "Enemy - Bulldozer" "Soldier - Truck" "Soldier - Flying" \
  18. "Soldier - Fly to the Switch" "Soldier - Flying (Alert)" "Unknown3" \
  19. "Soldier - Run to the Switch" "Guard Dog" "Mr. Arnold" "Basement Guard Dogs" \
  20. "Soldier - Guard to building 3" "Event - Dogs will appear" "Soldier - Pattern 3" \
  21. "Scorpion" "Big Boss" "Shoot Gunner" "Machine Gun Kid" "Laser fence" \
  22. "Fire Trooper" "Fire ball" "Hind-D" "Event - Incoming tank shells" \
  23. "Event - Guards will switch shifts" "Coward Duck" "Unknown8" \
  24. "Shoot Gunner - Bullet" "Power Switch" "Event - Snake Gets Captured" \
  25. "Event - Access to building 2" "Bullet 1" "Soldier - Stationary Guard" \
  26. "POW" "Ellen" "Grey Fox" "Dr. Petrovich" "Laser Camera" "36" "Fake Dr. Petrovich" \
  27. "Unknown9" "Soldier - Silencer Guards" "Unknown11" "Bullet 2" \
  28. "Machine Gun Kid - Bullet" "Bullet 3" "Tank - Bullet" "Boomerang" "Zzz" \
  29. "Unknown13" "Unknown14" "Unknown15" "44" "45" "46" "47" "48" "49" "4A" \
  30. "4B" "4C" "4D" "4E" "4F" "50" "51" "52" "53" "54" "55" "56" "57" "58" \
  31. "59" "5A" "5B" "5C" "5D" "5E" "5F" "60" "61" "62" "63" "64" "65" "66" ]
  32. set_help_text toggle_metal_gear_overlay \
  33. "Shows OSD widgets that help you play Metal Gear. Only useful if you
  34. are actually running this game... If you are not, you may get a lot of weird
  35. stuff on your screen :) It mostly shows Snake and enemy properties on screen
  36. and events that will happen."
  37. proc init {} {
  38. variable num_enemies
  39. variable max_hp
  40. variable punch_max_hp
  41. variable currentfield
  42. variable map_feature_enabled
  43. # Create OSD elements
  44. osd_widgets::msx_init metal_gear
  45. for {set i 0} {$i < $num_enemies} {incr i} {
  46. osd_widgets::create_power_bar metal_gear.powerbar$i 16 2 0xff0080b0 0x00000080 0xffffffC0
  47. osd_widgets::create_power_bar metal_gear.punchbar$i 16 2 0x0080ffb0 0x00000080 0xffffffC0
  48. set max_hp($i) 0
  49. set punch_max_hp($i) 0
  50. }
  51. osd_widgets::create_power_bar metal_gear.powerbarsnake 24 2 0x00ff00b0 0x00000080 0xffffffC0
  52. osd_widgets::create_power_bar metal_gear.boss 24 8 0x00ff00b0 0x00000080 0xffffffC0
  53. set currentfield 0
  54. if {$map_feature_enabled} {
  55. for {set y 0} {$y < 16} {incr y} {
  56. for {set x 0} {$x < 16} {incr x} {
  57. set field [expr {$x + ($y * 16)}]
  58. osd create rectangle metal_gear.field$field -x [expr {($x * 3) + 1}] -y [expr {($y * 3) + 1}] -relw 2 -relh 2 -rgba 0x0000ff80
  59. }
  60. }
  61. }
  62. # Start the overlay refresh
  63. update_overlay
  64. }
  65. proc update_impl {} {
  66. variable max_hp
  67. variable punch_max_hp
  68. variable num_enemies
  69. variable enemy_names
  70. variable currentfield
  71. variable map_feature_enabled
  72. # check for field change
  73. set newfield [peek 0xC130]
  74. if {$currentfield != $newfield} {
  75. set previousfield $currentfield
  76. set currentfield $newfield
  77. # clear out old HP values if field has changed
  78. for {set i 0} {$i < $num_enemies} {incr i} {
  79. set punch_max_hp($i) 0
  80. set max_hp($i) 0
  81. }
  82. if {$map_feature_enabled} {
  83. osd configure metal_gear.field$previousfield -rgba 0x00ff0080
  84. osd configure metal_gear.field$currentfield -rgba 0xffffff80
  85. }
  86. }
  87. for {set i 0; set addr 0xD000} {$i < $num_enemies} {incr i; incr addr 0x80} {
  88. set enemy_type [peek $addr]
  89. set enemy_hp [peek [expr {$addr + 0x0D}]]
  90. if {$enemy_type > 0 && $enemy_hp > 0} {
  91. set pos_x [peek [expr {$addr + 5}]]
  92. set pos_y [peek [expr {$addr + 3}]]
  93. if {$enemy_hp > $max_hp($i)} {
  94. set max_hp($i) $enemy_hp
  95. }
  96. set power [expr {1.00 * $enemy_hp / $max_hp($i)}]
  97. set text "HP: $enemy_hp $i [lindex $enemy_names $enemy_type] - #$enemy_type"
  98. osd_widgets::update_power_bar metal_gear.powerbar$i $pos_x $pos_y $power $text
  99. # only show the punch bar when the enemy can be punched
  100. set enemy_punch_hp [expr {3 - [peek [expr {$addr + 0x7A}]]}]
  101. if {$enemy_punch_hp > 0} {
  102. if {$enemy_punch_hp > $punch_max_hp($i)} {
  103. set punch_max_hp($i) $enemy_punch_hp
  104. }
  105. set punch_power [expr {1.00 * $enemy_punch_hp / $punch_max_hp($i)}]
  106. osd_widgets::update_power_bar metal_gear.punchbar$i $pos_x [expr {$pos_y + 5}] $punch_power ""
  107. } else {
  108. osd_widgets::update_power_bar metal_gear.punchbar$i -50 -50 0 ""
  109. }
  110. } else {
  111. osd_widgets::update_power_bar metal_gear.powerbar$i -50 -50 0 ""
  112. osd_widgets::update_power_bar metal_gear.punchbar$i -50 -50 0 ""
  113. }
  114. }
  115. # get stats for snake
  116. set snake_hp [peek 0xC131]
  117. set power [expr {$snake_hp / 48.0}]
  118. set poisoned [peek 0xC139]
  119. set pos_x [peek 0xC184]
  120. set pos_y [peek 0xc182]
  121. set text ""
  122. if {$poisoned == 1} {
  123. set power 0
  124. set text "POISONED "
  125. }
  126. append text "($pos_x,$pos_y) HP: $snake_hp"
  127. osd_widgets::update_power_bar metal_gear.powerbarsnake [expr {$pos_x - 13}] [expr {$pos_y + 20}] $power $text
  128. }
  129. proc update_overlay {} {
  130. variable metal_gear_overlay_active
  131. if {!$metal_gear_overlay_active} return
  132. # check if not in demo or weapon/item screen
  133. set c012 [peek 0xC012]
  134. if {$c012 == 0x00 || $c012 == 0x47 || $c012 == 0x50 || [peek 0xC151] != 0} {
  135. osd configure metal_gear -y 999
  136. } else {
  137. osd configure metal_gear -y 0
  138. update_impl
  139. }
  140. after frame [namespace code update_overlay]
  141. }
  142. proc toggle_metal_gear_overlay {} {
  143. variable metal_gear_overlay_active
  144. set metal_gear_overlay_active [expr {!$metal_gear_overlay_active}]
  145. if {$metal_gear_overlay_active} {
  146. init
  147. set text "Metal Gear overlay activated!"
  148. } else {
  149. osd destroy metal_gear
  150. set text "Metal Gear overlay deactivated."
  151. }
  152. osd::display_message $text info
  153. return $text
  154. }
  155. namespace export toggle_metal_gear_overlay
  156. };# namespace metal_gear_overlay
  157. namespace import metal_gear_overlay::*