_trainer.tcl 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. namespace eval trainer {
  2. set_help_text trainer "
  3. Usage:
  4. trainer see which trainer is currently active
  5. trainer <game> see which cheats are currently active in the trainer
  6. trainer <game> all activate all cheats in the trainer
  7. trainer <game> \[<cheat> ..\] toggle cheats on/off
  8. trainer deactivate deactivate trainers
  9. Examples:
  10. trainer Frogger all
  11. trainer Circus\ Charlie 1 2
  12. trainer Pippols lives \"jump shoes\"\
  13. When switching trainers, the currently active trainer will be deactivated.
  14. "
  15. variable trainers ""
  16. variable active_trainer ""
  17. variable items_active
  18. variable after_id 0
  19. proc load_trainers {} {
  20. variable trainers
  21. if {[dict size $trainers] == 0} {
  22. # source the trainer definitions (user may override system defaults) and ignore errors
  23. catch {source $::env(OPENMSX_SYSTEM_DATA)/scripts/_trainerdefs.tcl}
  24. catch {source $::env(OPENMSX_USER_DATA)/scripts/_trainerdefs.tcl}
  25. }
  26. return $trainers
  27. }
  28. set_tabcompletion_proc trainer [namespace code tab_trainer] false
  29. proc tab_trainer {args} {
  30. set trainers [load_trainers]
  31. if {[llength $args] == 2} {
  32. set result [dict keys $trainers]
  33. lappend result "deactivate"
  34. } else {
  35. set result [list]
  36. set name [lindex $args 1]
  37. if {[dict exists $trainers $name]} {
  38. set items [dict get $trainers $name items]
  39. set i 1
  40. foreach {item_name item_impl} $items {
  41. lappend result $item_name $i
  42. incr i
  43. }
  44. }
  45. lappend result "all"
  46. }
  47. return $result
  48. }
  49. proc trainer {args} {
  50. variable active_trainer
  51. variable items_active
  52. set trainers [load_trainers]
  53. if {[llength $args] > 0} {
  54. set name [lindex $args 0]
  55. if {$name ne "deactivate"} {
  56. set requested_items [lrange $args 1 end]
  57. if {![dict exists $trainers $name]} {
  58. error "no trainer for $name."
  59. }
  60. set same_trainer [string equal $name $active_trainer]
  61. set items [parse_items $name $requested_items]
  62. if {$same_trainer} {
  63. set new_items [list]
  64. foreach item1 $items item2 $items_active {
  65. lappend new_items [expr {$item1 ^ $item2}]
  66. }
  67. set items_active $new_items
  68. } else {
  69. deactivate
  70. set active_trainer $name
  71. set items_active $items
  72. execute
  73. }
  74. } else {
  75. deactivate
  76. return ""
  77. }
  78. }
  79. print
  80. }
  81. proc parse_items {name requested_items} {
  82. variable trainers
  83. set items [dict get $trainers $name items]
  84. set result [list]
  85. set i 1
  86. foreach {item_name item_impl} $items {
  87. lappend result [expr {($requested_items eq "all") ||
  88. ($i in $requested_items) ||
  89. ($item_name in $requested_items)}]
  90. incr i
  91. }
  92. return $result
  93. }
  94. proc print {} {
  95. variable trainers
  96. variable active_trainer
  97. variable items_active
  98. if {$active_trainer eq ""} {
  99. return "no trainer active"
  100. }
  101. set result [list]
  102. set items [dict get $trainers $active_trainer items]
  103. lappend result "active trainer: $active_trainer"
  104. set i 1
  105. foreach {item_name item_impl} $items item_active $items_active {
  106. set line "$i \["
  107. append line [expr {$item_active ? "x" : " "}]
  108. append line "\] $item_name"
  109. lappend result $line
  110. incr i
  111. }
  112. join $result \n
  113. }
  114. proc execute {} {
  115. variable trainers
  116. variable active_trainer
  117. variable items_active
  118. variable after_id
  119. set items [dict get $trainers $active_trainer items ]
  120. set repeat [dict get $trainers $active_trainer repeat]
  121. foreach {item_name item_impl} $items item_active $items_active {
  122. if {$item_active} {
  123. eval $item_impl
  124. }
  125. }
  126. set after_id [after {*}$repeat trainer::execute]
  127. }
  128. proc deactivate {} {
  129. variable after_id
  130. variable active_trainer
  131. after cancel $after_id
  132. set active_trainer ""
  133. }
  134. proc deactivate_after {event} {
  135. deactivate
  136. after $event "trainer::deactivate_after $event"
  137. }
  138. deactivate_after boot
  139. deactivate_after machine_switch
  140. proc create_trainer {name repeat items} {
  141. variable trainers
  142. dict set trainers $name [dict create items $items repeat $repeat]
  143. }
  144. namespace export trainer
  145. } ;# namespace trainer
  146. namespace import trainer::*