Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

params.gno

3.84 Kb · 112 lines
  1package game
  2
  3import "chain"
  4
  5// param is one tunable number of the game, with the bounds an admin has to
  6// stay within.
  7type param struct {
  8	key   string
  9	value int64
 10	min   int64
 11	max   int64
 12	doc   string
 13}
 14
 15// paramLeaderboardSize is the one param the realm itself consumes. Every
 16// other param is only stored here and applied by the game server.
 17const paramLeaderboardSize = "leaderboard_size"
 18
 19// defaultParams returns the registry with its default values. The order is
 20// the display order, in StateJSON as well as in Render.
 21func defaultParams() []*param {
 22	return []*param{
 23		{"plane_speed", 70, 20, 300, "cruise speed, m/s"},
 24		{"boost_speed", 130, 20, 600, "speed while boosting, m/s"},
 25		{"boost_capacity_ms", 4000, 0, 60000, "how long a full boost tank lasts, 0 disables boost"},
 26		{"boost_recharge_ms", 10000, 100, 600000, "time to refill an empty tank while not boosting"},
 27		{"turn_rate", 80, 20, 360, "pitch and turn responsiveness, deg/s"},
 28		{"plane_health", 100, 1, 1000, "hit points"},
 29		{"fire_cooldown_ms", 160, 50, 5000, "minimum time between shots"},
 30		{"bullet_speed", 400, 100, 2000, "m/s"},
 31		{"bullet_ttl_ms", 1500, 100, 10000, "bullet lifetime"},
 32		{"bullet_damage", 20, 1, 1000, "hit points removed per bullet"},
 33		{"respawn_ms", 3000, 0, 60000, "delay before a destroyed plane respawns"},
 34		{"balloon_respawn_ms", 6000, 0, 600000, "delay before a popped balloon comes back"},
 35		{paramLeaderboardSize, 10, 1, 100, "entries a leaderboard keeps, on-chain and on the server"},
 36		{"max_players", 64, 1, 1000, "server capacity"},
 37		{"bot_max", 2, 0, 16, "bots flying with a lone pilot, 0 for no bots"},
 38		{"bot_off_players", 5, 1, 64, "from this many pilots there are no bots"},
 39		{"bot_aim_error", 8, 0, 45, "how far a bot's shot can stray from its aim, degrees"},
 40		{"bot_fire_interval_ms", 900, 100, 10000, "minimum time between a bot's shots"},
 41	}
 42}
 43
 44// findParam returns the param registered under key, or nil. The registry is
 45// a dozen entries, a linear scan is cheaper than any index.
 46func findParam(key string) *param {
 47	for _, p := range params {
 48		if p.key == key {
 49			return p
 50		}
 51	}
 52	return nil
 53}
 54
 55// SetParam changes a game parameter. Admin only.
 56//
 57// The key must exist and the value must be within the bounds of that key,
 58// see Render("params"). Lowering leaderboard_size truncates the kill
 59// leaderboard right away. Raising it does not bring back the lines that were
 60// dropped: the list fills up again as kills come in.
 61func SetParam(cur realm, key string, value int64) {
 62	assertAdmin(0, cur)
 63	p := findParam(key)
 64	if p == nil {
 65		panic(errUnknownParam)
 66	}
 67	if value < p.min || value > p.max {
 68		panic("gnofly: " + key + " must be between " + itoa(p.min) + " and " + itoa(p.max))
 69	}
 70	p.value = value
 71	if key == paramLeaderboardSize {
 72		trimRankings()
 73	}
 74	bump()
 75	chain.Emit("ParamSet", "key", key, "value", itoa(value))
 76}
 77
 78// SetParamBounds changes the range SetParam accepts for a key. Owner only.
 79//
 80// The bounds are the guard rail between the owner and the admins: admins tune
 81// values within them, the owner decides how far tuning may go. The current
 82// value has to fit the new bounds, so that the registry never holds a value
 83// SetParam would refuse.
 84func SetParamBounds(cur realm, key string, min, max int64) {
 85	assertOwner(0, cur)
 86	p := findParam(key)
 87	if p == nil {
 88		panic(errUnknownParam)
 89	}
 90	if min < 0 || min > max {
 91		panic(errInvalidBounds)
 92	}
 93	// An empty leaderboard has no last line to compare a new total with.
 94	if key == paramLeaderboardSize && min < 1 {
 95		panic(errLeaderboardMin)
 96	}
 97	if p.value < min || p.value > max {
 98		panic(errValueOutOfBounds)
 99	}
100	p.min, p.max = min, max
101	bump()
102	chain.Emit("ParamBoundsSet", "key", key, "min", itoa(min), "max", itoa(max))
103}
104
105// Param returns the value of a game parameter. It panics on an unknown key.
106func Param(key string) int64 {
107	p := findParam(key)
108	if p == nil {
109		panic(errUnknownParam)
110	}
111	return p.value
112}