go: port item effects — potions, scrolls, options, call_it
- potions.c completed: quaff with all 14 potion effects, the PACT standard-fuse table (do_pot), raise_level; the see-invisible fruit- juice message is computed at quaff time as in C - scrolls.c in full: read_scroll with all 18 scroll effects including the magic-mapping map rewrite and identify dispatch, uncurse - options.c in full: the interactive options screen, get_bool/get_str/ get_inv_t/get_sf editors, ROGUEOPTS parsing (prefix matching, no- prefixed booleans, ~ expansion), strucpy - misc.c call_it via the get_str line editor - turn_see gets a DaemonID (C casts it to a fuse callback for the monster-detection potion) Tests: healing/confusion potions with fuse burn-down, enchant armor, hold monster, slow-monster zap, ROGUEOPTS parsing, and a regression test documenting the C wake_monster ISGREED/ISHELD quirk the port keeps faithfully.
This commit is contained in:
209
game/potions.go
209
game/potions.go
@@ -1,7 +1,212 @@
|
||||
package game
|
||||
|
||||
// potions.c — the visibility-related helpers arrive first; quaff and the
|
||||
// potion effect dispatch come with the effects phase.
|
||||
import "fmt"
|
||||
|
||||
// potions.c — functions for dealing with potions.
|
||||
|
||||
// pact describes a standard fuse-based potion (potions.c PACT).
|
||||
type pact struct {
|
||||
flags CreatureFlags
|
||||
daemon DaemonID
|
||||
time int
|
||||
high string // message when hallucinating
|
||||
straight string
|
||||
}
|
||||
|
||||
// pActions is potions.c p_actions[]. The P_SEEINVIS message is dynamic
|
||||
// (it names the fruit) and is computed in doPot.
|
||||
var pActions = [MaxPotions]pact{
|
||||
PConfuse: {IsHuh, DUnconfuse, HuhDuration,
|
||||
"what a tripy feeling!",
|
||||
"wait, what's going on here. Huh? What? Who?"},
|
||||
PLSD: {IsHalu, DComeDown, SeeDuration,
|
||||
"Oh, wow! Everything seems so cosmic!",
|
||||
"Oh, wow! Everything seems so cosmic!"},
|
||||
PSeeInvis: {CanSee, DUnsee, SeeDuration, "", ""},
|
||||
PBlind: {IsBlind, DSight, SeeDuration,
|
||||
"oh, bummer! Everything is dark! Help!",
|
||||
"a cloak of darkness falls around you"},
|
||||
PLevit: {IsLevit, DLand, HealTime,
|
||||
"oh, wow! You're floating in the air!",
|
||||
"you start to float in the air"},
|
||||
}
|
||||
|
||||
// quaff drinks a potion from the pack (potions.c quaff).
|
||||
func (g *RogueGame) quaff() {
|
||||
p := &g.Player
|
||||
obj := g.getItem("quaff", int(Potion))
|
||||
// Make certain that it is something that we want to drink
|
||||
if obj == nil {
|
||||
return
|
||||
}
|
||||
if obj.Type != Potion {
|
||||
if !g.Options.Terse {
|
||||
g.msg("yuk! Why would you want to drink that?")
|
||||
} else {
|
||||
g.msg("that's undrinkable")
|
||||
}
|
||||
return
|
||||
}
|
||||
if obj == p.CurWeapon {
|
||||
p.CurWeapon = nil
|
||||
}
|
||||
|
||||
// Calculate the effect it has on the poor guy.
|
||||
trip := p.On(IsHalu)
|
||||
g.leavePack(obj, false, false)
|
||||
switch obj.Which {
|
||||
case PConfuse:
|
||||
g.doPot(PConfuse, !trip)
|
||||
case PPoison:
|
||||
g.Items.Potions[PPoison].Know = true
|
||||
if p.IsWearing(RSustStr) {
|
||||
g.msg("you feel momentarily sick")
|
||||
} else {
|
||||
g.chgStr(-(g.rnd(3) + 1))
|
||||
g.msg("you feel very sick now")
|
||||
g.comeDown(0)
|
||||
}
|
||||
case PHealing:
|
||||
g.Items.Potions[PHealing].Know = true
|
||||
if p.Stats.HP += g.roll(p.Stats.Lvl, 4); p.Stats.HP > p.Stats.MaxHP {
|
||||
p.Stats.MaxHP++
|
||||
p.Stats.HP = p.Stats.MaxHP
|
||||
}
|
||||
g.sight(0)
|
||||
g.msg("you begin to feel better")
|
||||
case PStrength:
|
||||
g.Items.Potions[PStrength].Know = true
|
||||
g.chgStr(1)
|
||||
g.msg("you feel stronger, now. What bulging muscles!")
|
||||
case PMFind:
|
||||
p.Flags.Set(SeeMonst)
|
||||
g.Fuse(DTurnSee, 1, HuhDuration, After)
|
||||
if !g.turnSee(false) {
|
||||
g.msg("you have a %s feeling for a moment, then it passes",
|
||||
g.chooseStr("normal", "strange"))
|
||||
}
|
||||
case PTFind:
|
||||
// Potion of magic detection. Show the potions and scrolls
|
||||
show := false
|
||||
if len(g.Level.Objects) > 0 {
|
||||
g.scr.Hw.Clear()
|
||||
for _, tp := range g.Level.Objects {
|
||||
if tp.isMagic() {
|
||||
show = true
|
||||
g.scr.Hw.MvAddCh(tp.Pos.Y, tp.Pos.X, Magic)
|
||||
g.Items.Potions[PTFind].Know = true
|
||||
}
|
||||
}
|
||||
for _, mp := range g.Level.Monsters {
|
||||
for _, tp := range mp.Pack {
|
||||
if tp.isMagic() {
|
||||
show = true
|
||||
g.scr.Hw.MvAddCh(mp.Pos.Y, mp.Pos.X, Magic)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if show {
|
||||
g.Items.Potions[PTFind].Know = true
|
||||
g.showWin("You sense the presence of magic on this level.--More--")
|
||||
} else {
|
||||
g.msg("you have a %s feeling for a moment, then it passes",
|
||||
g.chooseStr("normal", "strange"))
|
||||
}
|
||||
case PLSD:
|
||||
if !trip {
|
||||
if p.On(SeeMonst) {
|
||||
g.turnSee(false)
|
||||
}
|
||||
g.StartDaemon(DVisuals, 0, Before)
|
||||
g.SeenStairs = g.seenStairs()
|
||||
}
|
||||
g.doPot(PLSD, true)
|
||||
case PSeeInvis:
|
||||
show := p.On(CanSee)
|
||||
g.doPot(PSeeInvis, false)
|
||||
if !show {
|
||||
g.invisOn()
|
||||
}
|
||||
g.sight(0)
|
||||
case PRaise:
|
||||
g.Items.Potions[PRaise].Know = true
|
||||
g.msg("you suddenly feel much more skillful")
|
||||
g.raiseLevel()
|
||||
case PXHeal:
|
||||
g.Items.Potions[PXHeal].Know = true
|
||||
if p.Stats.HP += g.roll(p.Stats.Lvl, 8); p.Stats.HP > p.Stats.MaxHP {
|
||||
if p.Stats.HP > p.Stats.MaxHP+p.Stats.Lvl+1 {
|
||||
p.Stats.MaxHP++
|
||||
}
|
||||
p.Stats.MaxHP++
|
||||
p.Stats.HP = p.Stats.MaxHP
|
||||
}
|
||||
g.sight(0)
|
||||
g.comeDown(0)
|
||||
g.msg("you begin to feel much better")
|
||||
case PHaste:
|
||||
g.Items.Potions[PHaste].Know = true
|
||||
g.After = false
|
||||
if g.addHaste(true) {
|
||||
g.msg("you feel yourself moving much faster")
|
||||
}
|
||||
case PRestore:
|
||||
if p.IsRing(Left, RAddStr) {
|
||||
addStr(&p.Stats.Str, -p.CurRing[Left].Arm)
|
||||
}
|
||||
if p.IsRing(Right, RAddStr) {
|
||||
addStr(&p.Stats.Str, -p.CurRing[Right].Arm)
|
||||
}
|
||||
if p.Stats.Str < p.MaxStats.Str {
|
||||
p.Stats.Str = p.MaxStats.Str
|
||||
}
|
||||
if p.IsRing(Left, RAddStr) {
|
||||
addStr(&p.Stats.Str, p.CurRing[Left].Arm)
|
||||
}
|
||||
if p.IsRing(Right, RAddStr) {
|
||||
addStr(&p.Stats.Str, p.CurRing[Right].Arm)
|
||||
}
|
||||
g.msg("hey, this tastes great. It make you feel warm all over")
|
||||
case PBlind:
|
||||
g.doPot(PBlind, true)
|
||||
case PLevit:
|
||||
g.doPot(PLevit, true)
|
||||
}
|
||||
g.status()
|
||||
// Throw the item away
|
||||
g.callIt(&g.Items.Potions[obj.Which])
|
||||
}
|
||||
|
||||
// raiseLevel: the guy just magically went up a level (potions.c
|
||||
// raise_level).
|
||||
func (g *RogueGame) raiseLevel() {
|
||||
g.Player.Stats.Exp = eLevels[g.Player.Stats.Lvl-1] + 1
|
||||
g.checkLevel()
|
||||
}
|
||||
|
||||
// doPot does a potion with standard setup: it uses a fuse and turns on a
|
||||
// flag (potions.c do_pot).
|
||||
func (g *RogueGame) doPot(typ int, knowit bool) {
|
||||
pp := &pActions[typ]
|
||||
if !g.Items.Potions[typ].Know {
|
||||
g.Items.Potions[typ].Know = knowit
|
||||
}
|
||||
t := g.spread(pp.time)
|
||||
if !g.Player.On(pp.flags) {
|
||||
g.Player.Flags.Set(pp.flags)
|
||||
g.Fuse(pp.daemon, 0, t, After)
|
||||
g.look(false)
|
||||
} else {
|
||||
g.Lengthen(pp.daemon, t)
|
||||
}
|
||||
high, straight := pp.high, pp.straight
|
||||
if typ == PSeeInvis {
|
||||
s := fmt.Sprintf("this potion tastes like %s juice", g.Fruit)
|
||||
high, straight = s, s
|
||||
}
|
||||
g.msg("%s", g.chooseStr(high, straight))
|
||||
}
|
||||
|
||||
// isMagic reports whether an object radiates magic (potions.c is_magic).
|
||||
func (o *Object) isMagic() bool {
|
||||
|
||||
Reference in New Issue
Block a user