protected virtual void UpdateSkill() { if (_coolTick == 0) { // 유효한 타겟인지 if (_target == null || _target.Room != Room) { _target = null; State = CreatureState.Moving; BroadcastMove(); return; } // 스킬이 아직 사용 가능한지 Vector2Int dir = (_target.CellPos - CellPos); int dist = dir.cellDistFromZero; bool canUseSkill = (dist <= _skillRange && (dir.x == 0 || dir.y == 0)); if (canUseSkill == false) { State = CreatureState.Moving; BroadcastMove(); return; } // 타게팅 방향 주시 MoveDir lookDir = GetDirFromVector(dir); if (Dir != lookDir) { Dir = lookDir; BroadcastMove(); } Skill skillData = null; DataManager.SkillDict.TryGetValue(1, out skillData); // 데미지 판정 _target.OnDamaged(this, skillData.damage + TotalAttack); // 스킬 사용 Broadcast S_Skill skill = new S_Skill() { Info = new SkillInfo() }; skill.ObjectId = Id; skill.Info.SkillId = skillData.id; Room.Broadcast(CellPos, skill); // 스킬 쿨타임 적용 int coolTick = (int)(1000 * skillData.cooldown); _coolTick = Environment.TickCount64 + coolTick; } if (_coolTick > Environment.TickCount64) { return; } _coolTick = 0; }
// C_Skill public void HandleSkill(Player player, C_Skill skillPacket) { if (player == null) { return; } ObjectInfo info = player.Info; if (info.PosInfo.State != CreatureState.Idle) { return; } // TODO : 스킬 사용가능한지 검증 // 통과 info.PosInfo.State = CreatureState.Skill; S_Skill skill = new S_Skill() { Info = new SkillInfo() }; skill.ObjectId = info.ObjectId; skill.Info.SkillId = skillPacket.Info.SkillId; // 유저가 보내준 스킬 Broadcast(player.CellPos, skill); Data.Skill skillData = null; if (DataManager.SkillDict.TryGetValue(skill.Info.SkillId, out skillData) == false) { return; } // 스킬 종류에 따른 로직 switch (skillData.skillType) { case SkillType.SkillAuto: // 평타 // 데미지 판정 Vector2Int skillPos = player.GetFrontCellPos(info.PosInfo.MoveDir); GameObject target = Map.Find(skillPos); if (target != null) { this.Push(target.OnDamaged, player, player.Info.StatInfo.Attack); } break; case SkillType.SkillProjectile: // 투사체 SpawnProjectile(player, skillData); break; case SkillType.SkillNone: break; default: return; } }
public static void S_SkillHandler(PacketSession session, IMessage packet) { S_Skill skillPacket = packet as S_Skill; GameObject go = Managers.Object.FindById(skillPacket.ObjectId); if (go == null) { return; } CreatureController cc = go.GetComponent <CreatureController>(); if (cc != null) { cc.UseSkill(skillPacket.Info.SkillId); } }
public static void S_SkillHandler(PacketSession session, IMessage packet) { S_Skill skillPacket = packet as S_Skill; // 여기서 찾은 PlayerId가 꼭 나라는 보장은 없다. 스킬은 아무나 쓰니깐 GameObject go = Managers.Object.FindById(skillPacket.ObjectId); if (go == null) { return; } // 정보를 고치기 위해 CreatureController에 접근 CreatureController pc = go.GetComponent <CreatureController>(); if (pc != null) { pc.UseSkill(skillPacket.Info.SkillId); } }
public void HandleSkill(Player player, C_Skill skillPacket) { if (player == null) { return; } ObjectInfo info = player.Info; if (info.PosInfo.State != CreatureState.Idle) { return; } // TODO : 스킬 사용 가능 여부 체크 info.PosInfo.State = CreatureState.Skill; S_Skill skill = new S_Skill() { Info = new SkillInfo() }; skill.ObjectId = info.ObjectId; skill.Info.SkillId = skillPacket.Info.SkillId; Broadcast(skill); Data.Skill skillData = null; if (DataManager.SkillDict.TryGetValue(skillPacket.Info.SkillId, out skillData) == false) { return; } switch (skillData.skillType) { case SkillType.SkillAuto: { Vector2Int skillPos = player.GetFrontCellPos(info.PosInfo.MoveDir); GameObject target = Map.Find(skillPos); if (target != null) { Console.WriteLine("Hit GameObject !"); } } break; case SkillType.SkillProjectile: { Arrow arrow = ObjectManager.Instance.Add <Arrow>(); if (arrow == null) { return; } arrow.Owner = player; arrow.Data = skillData; arrow.PosInfo.State = CreatureState.Moving; arrow.PosInfo.MoveDir = player.PosInfo.MoveDir; arrow.PosInfo.PosX = player.PosInfo.PosX; arrow.PosInfo.PosY = player.PosInfo.PosY; arrow.Speed = skillData.projectile.speed; Push(EnterGame, arrow); } break; } }
public static void S_SkillHandler(PacketSession session, IMessage packet) // 무언가 스킬 사용 { S_Skill skillPacket = packet as S_Skill; }
protected virtual void UpdateSkill() { // _coolTick이 0이라는것은 스킬 사용할 준비가 완료됐음을 뜻함 if (_coolTick == 0) { // 유효한 타겟인지 체크 if (_target == null || _target.Room != Room || _target.Hp == 0) { _target = null; State = CreatureState.Moving; BroadcastMove(); // 좀 비효율적이지만.. return; } // 스킬이 아직 사용 가능한지 Vector2Int dir = (_target.CellPos - CellPos); int dist = dir.cellDistFromZero; bool canUseSkill = (dist <= _skillRange && (dir.x == 0 || dir.y == 0)); if (canUseSkill == false) { // 스킬을 사용할 수 없는 상태가 됨 // 플레이어가 도망가거나 게임 자체를 나가거나 할 때 그걸 다시 쫓을지는 Moving 상태에서 판단 State = CreatureState.Moving; BroadcastMove(); return; } // 타게팅 방향 주시 MoveDir lookDir = GetDirFromVec(dir); // 상대방 - 내위치 = 내가 상대방을 바라보는 방향 if (Dir != lookDir) { Dir = lookDir; // 모가지를 돌리고 BroadcastMove(); // 알림 } Skill skillData = null; // 몬스터 시트를 따로 빼서 몬스터에 연결된 스킬과 아이디를 맵핑 DataManager.SkillDict.TryGetValue(1, out skillData); // 데미지 판정 _target.OnDamaged(this, skillData.damage + Stat.Attack); // 스킬 사용 Broadcast S_Skill skill = new S_Skill() { Info = new SkillInfo() }; skill.ObjectId = Id; skill.Info.SkillId = skillData.id; Room.Broadcast(skill); // 몹이 스킬을 쓴다고 알림 // 스킬 쿨타임 시작 int coolTick = (int)(1000 * skillData.cooldown); // 단위 ms임 _coolTick = Environment.TickCount64 + coolTick; // 다음 tick 시간 구함 } // 다시 스킬을 사용할 준비가 됐는지 여부 if (_coolTick > Environment.TickCount64) { return; } // 햇갈릴수도 있겠네 _coolTick = 0; //_coolTick이 0이면 스킬사용 준비가 됐다는 뜻이다. }
// GameRoom의 JobSerilizer에 의해 실행되기 때문에 EnterGame같은거 직접 불러도 됨 public void HandleSkill(Player player, C_Skill skillPacket) { if (player == null) // player가 지금 GameRoom에 소속되었는지도 체크 { return; } // 스킬분기처리.. 몇 개 없다는 가정하에 // 스킬이 많아지면 Skill 클래스를 따로 파서 플레이어에 주입하는게 낫다 ObjectInfo info = player.Info; if (info.PosInfo.State != CreatureState.Idle) { return; } // 스킬 사용 가능 여부 체크 // 스킬 애니메이션 맞춰주는 부분 info.PosInfo.State = CreatureState.Skill; S_Skill skill = new S_Skill() { Info = new SkillInfo() }; // info도 클래스임 skill.ObjectId = info.ObjectId; skill.Info.SkillId = skillPacket.Info.SkillId; // 나중에 시트로 뺄거야 Broadcast(skill); // 에코서버마냥 전파한다 // 이제 DB에서 Id에 해당하는 스킬데이터를 뽑아온다 Data.Skill skillData = null; if (DataManager.SkillDict.TryGetValue(skillPacket.Info.SkillId, out skillData) == false) { return; } // id에 해당하는 스킬이 있다 switch (skillData.skillType) { case SkillType.SkillAuto: { // 주먹질 // 데미지 판정 -> 항상 치팅 대비 // 내 공격방향에 적이 있나 없나 체크 // GetFrontCellPos에 MoveDir.None 처리가 없으니 // 항상 공격자의 위치를 반환해서 아무대나 떄려도 타격이 되는 문제가 있었음 // MoveDir.None이 그냥 키입력 여부를 받는거라 서버에는 필요없으므로 전체적으로 없애기로함 Vector2Int skillPos = player.GetFrontCellPos(info.PosInfo.MoveDir); GameObject target = Map.Find(skillPos); if (target != null) { Console.WriteLine("Hit GameObject!"); } } break; case SkillType.SkillProjectile: { // 화살 생성 // 클라에서도 화살이 날아가는것을 계산하고 있어야 치팅을 방지할수 있다. // 어떤 투사체인지 구분할수 있는게 필요 (지금은 화살만..) Arrow arrow = ObjectManager.Instance.Add <Arrow>(); if (arrow == null) { return; } // 데이터 대입 arrow.Owner = player; arrow.Data = skillData; // 투사체를 생성한 주체(스킬)의 정보를 저장 arrow.PosInfo.State = CreatureState.Moving; arrow.PosInfo.MoveDir = player.PosInfo.MoveDir; arrow.PosInfo.PosX = player.PosInfo.PosX; arrow.PosInfo.PosY = player.PosInfo.PosY; arrow.Speed = skillData.projectile.speed; // 직접 불러서 해도 전혀 문제없긴함 EnterGame(arrow) Push(EnterGame, arrow); // 치팅방지 + 코드재사용(화살이 생성됐음을 모두에게 알림) } break; } }