-
Notifications
You must be signed in to change notification settings - Fork 16
/
CharacterActions.cs
183 lines (150 loc) · 6.29 KB
/
CharacterActions.cs
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
using System;
using System.Linq;
using AutomaticTypeMapper;
using EOLib.Domain.Extensions;
using EOLib.Domain.NPC;
using EOLib.Domain.Spells;
using EOLib.IO.Repositories;
using EOLib.Net;
using EOLib.Net.Communication;
namespace EOLib.Domain.Character
{
[AutoMappedType]
public class CharacterActions : ICharacterActions
{
private readonly IPacketSendService _packetSendService;
private readonly ICharacterProvider _characterProvider;
private readonly IESFFileProvider _spellFileProvider;
public CharacterActions(IPacketSendService packetSendService,
ICharacterProvider characterProvider,
IESFFileProvider spellFileProvider)
{
_packetSendService = packetSendService;
_characterProvider = characterProvider;
_spellFileProvider = spellFileProvider;
}
public void Face(EODirection direction)
{
var packet = new PacketBuilder(PacketFamily.Face, PacketAction.Player)
.AddChar((byte) direction)
.Build();
_packetSendService.SendPacket(packet);
}
public void Walk()
{
var admin = _characterProvider.MainCharacter.NoWall &&
_characterProvider.MainCharacter.AdminLevel != AdminLevel.Player;
var renderProperties = _characterProvider.MainCharacter.RenderProperties;
var packet = new PacketBuilder(PacketFamily.Walk, admin ? PacketAction.Admin : PacketAction.Player)
.AddChar((byte) renderProperties.Direction)
.AddThree(DateTime.Now.ToEOTimeStamp())
.AddChar((byte)renderProperties.GetDestinationX())
.AddChar((byte)renderProperties.GetDestinationY())
.Build();
_packetSendService.SendPacket(packet);
}
public void Attack()
{
var packet = new PacketBuilder(PacketFamily.Attack, PacketAction.Use)
.AddChar((byte) _characterProvider.MainCharacter.RenderProperties.Direction)
.AddThree(DateTime.Now.ToEOTimeStamp())
.Build();
_packetSendService.SendPacket(packet);
}
public void ToggleSit()
{
var renderProperties = _characterProvider.MainCharacter.RenderProperties;
var sitAction = renderProperties.SitState == SitState.Standing
? SitAction.Sit
: SitAction.Stand;
var packetFamily = renderProperties.SitState == SitState.Chair
? PacketFamily.Chair
: PacketFamily.Sit;
var packet = new PacketBuilder(packetFamily, PacketAction.Request)
.AddChar((byte)sitAction)
.Build();
_packetSendService.SendPacket(packet);
}
public void SitInChair()
{
var rp = _characterProvider.MainCharacter.RenderProperties;
var action = rp.SitState == SitState.Chair ? SitAction.Stand : SitAction.Sit;
var packet = new PacketBuilder(PacketFamily.Chair, PacketAction.Request)
.AddChar((byte)action)
.AddChar((byte)rp.GetDestinationX())
.AddChar((byte)rp.GetDestinationY())
.Build();
_packetSendService.SendPacket(packet);
}
public void PrepareCastSpell(int spellId)
{
var packet = new PacketBuilder(PacketFamily.Spell, PacketAction.Request)
.AddShort((short)spellId)
.AddThree(DateTime.Now.ToEOTimeStamp())
.Build();
_packetSendService.SendPacket(packet);
}
public void CastSpell(int spellId, ISpellTargetable target)
{
var data = _spellFileProvider.ESFFile.Single(x => x.ID == spellId);
var action = data.Target == IO.SpellTarget.Self
? PacketAction.TargetSelf
: data.Target == IO.SpellTarget.Normal
? PacketAction.TargetOther
: data.Target == IO.SpellTarget.Group
? PacketAction.TargetGroup
: throw new InvalidOperationException("Spell ID has unknown spell target");
IPacketBuilder builder = new PacketBuilder(PacketFamily.Spell, action);
if (data.Target == IO.SpellTarget.Group)
{
// todo: implement packet handling for group target spells
builder = builder
.AddShort((short)spellId)
.AddThree(DateTime.Now.ToEOTimeStamp());
}
else
{
var spellTargetType = target is INPC
? SpellTargetType.NPC
: target is ICharacter
? SpellTargetType.Player
: throw new InvalidOperationException("Invalid spell target specified, must be player or character");
builder = builder.AddChar((byte)spellTargetType);
if (data.Target == IO.SpellTarget.Normal)
{
builder = builder
.AddChar(1) // unknown
.AddShort(1) // unknown
.AddShort((short)spellId)
.AddShort((short)target.Index)
.AddThree(DateTime.Now.ToEOTimeStamp());
}
else
{
builder = builder
.AddShort((short)spellId)
.AddInt(DateTime.Now.ToEOTimeStamp());
}
}
_packetSendService.SendPacket(builder.Build());
}
public void Emote(Emote whichEmote)
{
var packet = new PacketBuilder(PacketFamily.Emote, PacketAction.Report)
.AddChar((byte)whichEmote)
.Build();
_packetSendService.SendPacket(packet);
}
}
public interface ICharacterActions
{
void Face(EODirection direction);
void Walk();
void Attack();
void ToggleSit();
void SitInChair();
void PrepareCastSpell(int spellId);
void CastSpell(int spellId, ISpellTargetable target);
void Emote(Emote whichEmote);
}
}