-
Notifications
You must be signed in to change notification settings - Fork 0
/
doors.go
107 lines (100 loc) · 2.71 KB
/
doors.go
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
package events
import (
"github.com/qbradq/sharduo/internal/game"
"github.com/qbradq/sharduo/lib/uo"
)
func init() {
reg("UseDoor", UseDoor)
}
var doorOpenSounds = map[string]uo.Sound{
"MetalDoor": 0xEC,
"BarredMetalDoor": 0xEC,
"RattanDoor": 0xEB,
"WoodenDoor": 0xEA,
"LightWoodenDoor": 0xEA,
"StrongWoodenDoor": 0xEA,
"IronGateShort": 0xEC,
"IronGate": 0xEC,
"LightWoodenGate": 0xEB,
"DarkWoodenGate": 0xEB,
}
var doorCloseSounds = map[string]uo.Sound{
"MetalDoor": 0xF3,
"BarredMetalDoor": 0xF3,
"RattanDoor": 0xF2,
"WoodenDoor": 0xF1,
"LightWoodenDoor": 0xF1,
"StrongWoodenDoor": 0xF1,
"IronGateShort": 0xF3,
"IronGate": 0xF3,
"LightWoodenGate": 0xF2,
"DarkWoodenGate": 0xF2,
}
var doorCloseTimers = map[uo.Serial]uo.Serial{}
func doUseDoor(receiver, source game.Object, force bool) bool {
sm, ok := source.(game.Mobile)
if !ok || sm.NetState() == nil {
return false
}
// Range check
if !force && receiver.Location().XYDistance(source.Location()) > uo.MaxUseRange {
sm.NetState().Cliloc(nil, 502803) // It's too far away.
return false
}
// Line of sight check
if !force && !sm.HasLineOfSight(receiver) {
sm.NetState().Cliloc(nil, 500950) // You cannot see that.
return false
}
// Select door offsets, sounds, ect
ri, ok := receiver.(game.Item)
if !ok {
return false
}
l := ri.Location()
ofs := uo.DoorOffsets[int(ri.Facing())]
var s uo.Sound
if ri.Flipped() {
l.X -= ofs.X
l.Y -= ofs.Y
s = doorCloseSounds[ri.TemplateName()]
} else {
l.X += ofs.X
l.Y += ofs.Y
s = doorOpenSounds[ri.TemplateName()]
}
// Skip map fit check, not all doors on the retail map have clearance with
// the terrain to properly open
game.GetWorld().Map().ForceRemoveObject(ri)
ri.Flip()
ri.SetLocation(l)
ri.SetDefForGraphic(ri.Graphic())
game.GetWorld().Map().ForceAddObject(ri)
game.GetWorld().Map().PlaySound(s, l)
// Auto-close functionality
if ri.Flipped() {
// Door is now open, setup a timer to close it
doorCloseTimers[ri.Serial()] = game.NewTimer(uo.DurationSecond*20, "UseDoor", ri, source, true, true)
} else {
// Door is now closed, make sure there are no pending timers
s, found := doorCloseTimers[ri.Serial()]
if found {
game.CancelTimer(s)
delete(doorCloseTimers, ri.Serial())
}
}
return true
}
func UseDoor(receiver, source game.Object, v any) bool {
force, ok := v.(bool)
if !ok {
force = false
}
doors := game.GetWorld().Map().ItemBaseQuery("BaseDoor", receiver.Location().BoundsByRadius(1))
for _, d := range doors {
if !doUseDoor(d, source, force) {
return false
}
}
return true
}