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