aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_move.go
blob: b95f5c5bb9260707a06132d562e1b5e6605aecd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package game

import (
	"fmt"

	"thirdcollapse/internal/combat"
	"thirdcollapse/internal/net"
	"thirdcollapse/internal/player"
)

func (g *Game) doMove(sess *net.Session, dir string) {
	p := sess.Player.(*player.Player)
	exitDir := g.World.ResolveExit(dir)
	if exitDir == "" {
		sess.WriteLine("Go where?")
		return
	}

	room, err := g.World.LoadRoom(p.RoomID)
	if err != nil {
		sess.WriteLine("You can't move from here.")
		return
	}

	exitDef, ok := room.Exits[exitDir]
	if !ok {
		sess.WriteLine("You can't go that way.")
		return
	}

	if exitDef.Condition != nil && !g.CheckExitCondition(exitDef.Condition) {
		msg := exitDef.BlockedMessage
		if msg == "" {
			msg = fmt.Sprintf("The way %s is blocked.", exitDir)
		}
		sess.WriteLine(msg)
		return
	}

	targetID := exitDef.Room

	_, err = g.World.LoadRoom(targetID)
	if err != nil {
		sess.WriteLine("That path seems blocked.")
		return
	}

	if cs := combat.GetCombat(p.Name); cs != nil && cs.LockedTicks > 0 {
		sess.WriteLine(fmt.Sprintf("You are locked in combat for another %d tick%s!", cs.LockedTicks, plural(cs.LockedTicks)))
		return
	}

	g.stopCombat(p.Name)

	if p.Action != nil {
		g.CancelAction(p)
	}

	oldRoom := p.RoomID
	p.RoomID = targetID
	g.AccountStore.SaveCharacter(p)

	g.World.SeedGroundItems(p.RoomID)
	g.seedRoomMobs(p.RoomID)
	g.ensureRoomObjects(p.RoomID)

	if g.Hub != nil {
		for _, other := range g.Hub.PlayersInRoom(oldRoom) {
			if other != sess {
				other.WriteLine(fmt.Sprintf("\n%s leaves to the %s.", p.Name, exitDir))
			}
		}
		g.Hub.EnterRoom(sess, targetID)
		for _, other := range g.Hub.PlayersInRoom(targetID) {
			if other != sess {
				other.WriteLine(fmt.Sprintf("\n%s arrives.", p.Name))
			}
		}
	}

	sess.WriteLine(fmt.Sprintf("\nYou walk %s.", exitDir))
	if p.Toggles["description"] {
		g.doLook(sess)
	} else {
		targetRoom, _ := g.World.LoadRoom(targetID)
		if targetRoom != nil {
			sess.WriteLine(targetRoom.Name)
		}
	}

	g.RunEnterSteps(sess, targetID)
}

func (g *Game) seedRoomMobs(roomID int) {
	room, err := g.World.LoadRoom(roomID)
	if err != nil || len(room.Mobs) == 0 {
		return
	}
	g.MobStore.SeedMobs(roomID, room.Mobs)
}

func (g *Game) ensureRoomObjects(roomID int) {
	room, err := g.World.LoadRoom(roomID)
	if err != nil {
		return
	}
	var ids []string
	for _, obj := range room.Objects {
		ids = append(ids, obj.ID)
	}
	g.World.EnsureObjectStates(roomID, ids)
	for _, obj := range room.Objects {
		def, err := g.ObjectStore.Load(obj.ID)
		if err != nil {
			continue
		}
		g.World.SetObjName(roomID, obj.ID, def.Name)
		if len(obj.WanderRooms) > 0 {
			g.World.SetObjWander(roomID, obj.ID, obj.WanderRooms, obj.WanderInterval)
		}
	}
}