Post

(TIL) 2025-03-05 FINAL(22)

(TIL) 2025-03-05 FINAL(22)

장비 아이템 조합


오늘 작업한 내용은 장비 조합이다. 각 부위별로 조합이 가능하며 같은 등급일때는 100% 성공률을 갖고 다른 등급과 조합을 할 경우 등급에 따른 가중치를 더하여 확률이 결정된다.

코드 작업

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
const equipmentUpgradeHandler = ({ socket, payload, userId }) => {
  const { itemCode1, itemCode2 } = payload;

  // 데이터 체크
  if (!itemCode1 || !itemCode2) {
    throw new CustomError(`아이템이 부족하여 조합할 수 없습니다.`);
  }

  // 부위 여부 체크
  const item1Str = itemCode1.toString();
  const item2Str = itemCode2.toString();
  if (item1Str.length !== item2Str.length || item1Str[0] !== item2Str[0]) {
    throw new CustomError('조합이 불가능합니다.');
  }
  const itemType = item1Str[0];

  // 유저 객체 조회
  const user = userSession.getUser(userId);
  if (!user) throw new CustomError(`User ID : (${userId}): 유저 정보가 없습니다.`);

  // 룸 객체 조회
  const game = gameSession.getGame(user.getGameId());
  if (!game) throw new CustomError(`Game ID(${user.getGameId()}): Game 정보가 없습니다.`);

  //인벤토리에 빈공간이 있는지 확인
  const checkRoom = (e) => e === 0;
  const emptyIndex = user.player.inventory.findIndex(checkRoom);
  if (emptyIndex === -1) CustomError(`인벤토리에 공간이 없어 조합할 수 없습니다.`);

  // 무기, 방어구 에셋 불러오기
  const { weapon, armorAccessory, armorHelmet, armorBottom, armorShoes, armorTop, upgradeRate } =
    getGameAssets();

  const items = [itemCode1, itemCode2];
  const itemDatas = [];
  const itemGrades = [];

  // 에셋 데이터 검증
  items.forEach((item) => {
    let data = null;
    /**
     * 101 ~ 120 무기 , 301 ~ 305 갑옷
     * 401 ~ 405 바지 , 501 ~ 505 신발
     * 601 ~ 605 투구 , 701 ~ 705 악세
     */
    switch (item.toString()[0]) {
      case '1':
        data = weapon.data.find((data) => data.code === item);
        break;
      case '3':
        data = armorTop.data.find((data) => data.code === item);
        break;
      case '4':
        data = armorBottom.data.find((data) => data.code === item);
        break;
      case '5':
        data = armorShoes.data.find((data) => data.code === item);
        break;
      case '6':
        data = armorHelmet.data.find((data) => data.code === item);
        break;
      case '7':
        data = armorAccessory.data.find((data) => data.code === item);
        break;
      default:
        throw new CustomError('존재하지않는 아이템 입니다.');
    }
    if (!data) throw new CustomError('존재하지않는 아이템 입니다.');

    itemDatas.push(data);
    itemGrades.push(config.game.item.equipmentGrades.findIndex((grade) => grade === data.grade));
  });

  let isSuccess = false;
  let createGrade = null;
  if (itemGrades[0] !== itemGrades[1]) {
    /***********
     * 다른 등급
     */
    // 가중치 합산
    const totalWeight =
      upgradeRate.data[config.game.item.equipmentGrades[itemGrades[0]]] +
      upgradeRate.data[config.game.item.equipmentGrades[itemGrades[1]]];
    // 확률 처리
    const random = Math.floor(Math.random() * 100) + 1;

    const maxIndex = Math.max(itemGrades[0], itemGrades[1]);
    // 성공 실패 여부
    if (random <= totalWeight) {
      // 성공
      isSuccess = true;
      createGrade =
        config.game.item.equipmentGrades.length - 1 > maxIndex
          ? config.game.item.equipmentGrades[maxIndex + 1]
          : config.game.item.equipmentGrades[maxIndex];
    } else {
      //실패
      createGrade = config.game.item.equipmentGrades[maxIndex];
    }
  } else {
    /***********
     * 동일 등급
     */
    isSuccess = true;
    createGrade =
      config.game.item.equipmentGrades.length - 1 === itemGrades[0]
        ? config.game.item.equipmentGrades[itemGrades[0]]
        : config.game.item.equipmentGrades[itemGrades[0] + 1];
  }

  // 등급에 따른 아이템 생성
  let equipmentList = null;
  switch (itemType) {
    case '1':
      equipmentList = weapon.data.filter((data) => data.grade === createGrade);
      break;
    case '3':
      equipmentList = armorTop.data.filter((data) => data.grade === createGrade);
      break;
    case '4':
      equipmentList = armorBottom.data.filter((data) => data.grade === createGrade);
      break;
    case '5':
      equipmentList = armorShoes.data.filter((data) => data.grade === createGrade);
      break;
    case '6':
      equipmentList = armorHelmet.data.filter((data) => data.grade === createGrade);
      break;
    case '7':
      equipmentList = armorAccessory.data.filter((data) => data.grade === createGrade);
      break;
    default:
      throw new CustomError('존재하지않는 아이템 입니다.');
  }

  // 유저 인벤토리에서 재료 삭제
  user.player.removeItem(itemCode1, 1);
  user.player.removeItem(itemCode2, 1);

  const createRandom = Math.floor(Math.random() * equipmentList.length);
  const createEquipment = equipmentList[createRandom];
  console.log(
    `조합에 ${isSuccess ? '성공' : '실패'} 하여 ${createGrade} 등급의 새로운 아이템이 생성되었습니다.`,
    createEquipment,
  );

  // 유저 인벤토리에 아이템 생성
  user.player.addItem(createEquipment.code, 1, emptyIndex);

  const sendPayload = {
    success: isSuccess,
    itemCode1: itemCode1,
    itemCode2: itemCode2,
    itemResultCode: createEquipment.code,
    playerId: userId,
  };

  const packet = [config.packetType.S_ITEM_COMBINATION_NOTIFICATION, sendPayload];
  game.broadcast(packet);
};

테스트

  1. 조합란에서 조합할 장비 선택 사진1 사진1 사진1

  2. 조합 성공! 사진1

This post is licensed under CC BY 4.0 by the author.