
먼저 어떤 몹을 만들지 구체적인 목표를 정했음.
- 레벨 시스템: 공격 성공 시 경험치를 얻고 레벨업함.
- 다중 투사체: 레벨이 오를수록 한 번에 던지는 삼지창 개수가 늘어남 (Lv.1 = 1개, Lv.2 = 2개...).
- 능력치 강화: 레벨업 시 최대 체력과 적 인식 범위(Follow Range)가 증가함.
- 고정 데미지: 삼지창의 데미지는 레벨과 상관없이 1로 고정.
- 넉백 강화: 삼지창에 맞은 적이 밀려나는 거리가 레벨에 비례해 늘어남.
- 아군 보호: 다른 좀비나 아군 유닛을 실수로 공격해도 피해를 주지 않고, 아군에게 맞아도 반격하지 않음.
Step 1. 기본 뼈대 만들기
새로운 기능을 깔끔하게 관리하기 위해 feature 폴더 아래에 trident_tempest_zombie 라는 새 패키지를 생성함.
그리고 그 안에 새로운 몹을 위한 필수 파일 5개를 만들어줬음.
- TridentTempestZombieEntity.java: 몹의 핵심 데이터와 행동 로직을 담을 파일.
- TridentTempestZombieEntityTypeInit.java: 이 몹을 게임 시스템에 '엔티티 타입'으로 등록하는 파일.
- TridentTempestZombieItemInit.java: 몹을 소환하는 '스폰 알'을 아이템으로 등록하는 파일.
- TridentTempestZombieEvents.java: 몹의 속성(체력, 공격력 등)을 정의하고, 렌더러를 등록하고, 공격/피격 같은 이벤트를 처리할 파일.
- TridentTempestZombieRenderer.java: 몹의 외형과 머리 위 UI(레벨, 체력바)를 그리는 파일.
Step 2. 핵심 로직 구현 (TridentTempestZombieEntity.java)
가장 중요한 엔티티 파일부터 코드를 채워나갔음.
1. 레벨 시스템 구현
몹의 레벨, 경험치 데이터를 서버와 클라이언트 간에 동기화하기 위해 EntityDataAccessor를 사용함.
Generated java
// TridentTempestZombieEntity.java
private static final EntityDataAccessor<Integer> DATA_MOB_LEVEL = SynchedEntityData.defineId(...);
private static final EntityDataAccessor<Float> DATA_EXPERIENCE = SynchedEntityData.defineId(...);
공격 성공 시 경험치를 더하고, 필요 경험치를 넘으면 레벨업을 시키는 addExperience 메소드를 만듦.
// TridentTempestZombieEntity.java
public void addExperience(float amount) {
// ...
while (currentExp >= requiredExp) {
currentExp -= requiredExp;
currentLevel++;
requiredExp = 10 + (currentLevel - 1) * 5; // 레벨업 필요 경험치 공식
this.onLevelUp(); // 레벨업!
}
// ...
}
2. 능력치 강화 로직
레벨업 시 onLevelUp() 메소드가 호출되면, updateAttributes()를 통해 실제 능력치를 강화시킴. AttributeModifier를 사용해서 최대 체력과 추적 범위를 레벨에 비례해 영구적으로 증가시켰음.
// TridentTempestZombieEntity.java
private void updateAttributes() {
AttributeInstance healthAttribute = this.getAttribute(Attributes.MAX_HEALTH);
AttributeInstance followRangeAttribute = this.getAttribute(Attributes.FOLLOW_RANGE);
double levelBonus = getMobLevel() - 1;
// 레벨당 체력 +5
healthAttribute.addPermanentModifier(new AttributeModifier(HEALTH_BOOST_ID, "Level Health Boost", 5.0 * levelBonus, ...));
// 레벨당 추적 범위 +3
followRangeAttribute.addPermanentModifier(new AttributeModifier(FOLLOW_RANGE_BOOST_ID, "Level Follow Range Boost", 3.0 * levelBonus, ...));
}
3. 삼지창 연사 공격 구현

이 몹의 핵심 기능. performRangedAttack 메소드에서 for 루프를 사용해 현재 레벨만큼 삼지창을 반복해서 생성하고 발사하도록 함.
여기서 데미지는 1로 고정하고(setBaseDamage(1.0D)), 넉백은 레벨에 비례하도록(setKnockback((byte)this.getMobLevel())) 설정함.
// TridentTempestZombieEntity.java
@Override
public void performRangedAttack(LivingEntity target, float distanceFactor) {
int tridentCount = this.getMobLevel(); // 레벨만큼 삼지창 발사
for (int i = 0; i < tridentCount; i++) {
ThrownTrident tridentEntity = new ThrownTrident(this.level, this, new ItemStack(Items.TRIDENT));
tridentEntity.setBaseDamage(1.0D); // 데미지 1 고정
tridentEntity.setKnockback((byte)this.getMobLevel()); // 넉백 강화
// ... 발사 로직 ...
this.level.addFreshEntity(tridentEntity);
}
this.playSound(...); // 사운드는 한 번만
}
Step 3. 아군 보호 로직 추가 (중요!)
원거리 공격을 하다 보면 실수로 아군을 맞출 수 있고, 아군에게 맞았다고 반격하면 팀킬 대잔치가 벌어짐. 이걸 막는 로직을 추가함.
1. 아군에게 피격 시 반격 방지
HurtByTargetGoal을 익명 클래스로 오버라이드해서, 공격자가 아군(Zombie 또는 IZombieAlly)이면 반격 목표를 설정하지 않도록 수정함.
// TridentTempestZombieEntity.java 의 registerGoals()
this.targetSelector.addGoal(1, new HurtByTargetGoal(this) {
@Override
public boolean canUse() {
LivingEntity attacker = this.mob.getLastHurtByMob();
// 공격자가 아군이면 false 반환
if (attacker == null || attacker instanceof Zombie || attacker instanceof IZombieAlly) {
return false;
}
return super.canUse();
}
});
2. 아군에게 가하는 피해 무효화
TridentTempestZombieEvents.java의 onLivingHurt 이벤트에서, 공격의 주체는 우리 좀비인데 피해자가 아군일 경우, 이벤트 자체를 취소시켜 피해량이 0이 되게 만듦.
// TridentTempestZombieEvents.java 의 onLivingHurt()
if (tempestZombieOwner != null) { // 공격자가 우리 좀비가 맞다면
// 피해자가 아군인지 확인
if (victim instanceof Zombie || victim instanceof IZombieAlly) {
event.setAmount(0); // 피해량 0
return; // 즉시 종료 (경험치도 안 오름)
}
// 적을 때렸을 때만 경험치 획득
tempestZombieOwner.addExperience(event.getAmount());
}
Step 4. 리소스 등록 및 마무리
마지막으로 스폰 알의 모양과 이름을 설정하고, 만든 파일들을 메인 클래스에 등록해주면 끝.
1. 스폰 알 모델 (trident_tempest_zombie_spawn_egg.json)
스폰 알이 보라돌이/검정 체크무늬로 나오지 않게 하려면, 바닐라의 스폰 알 템플릿을 부모로 지정해줘야 함.
{
"parent": "minecraft:item/template_spawn_egg"
}
2. 언어 파일 (en_us.json)
아이템의 이름을 등록해줌.
{
"item.mymod.trident_tempest_zombie_spawn_egg": "Trident Tempest Zombie Spawn Egg"
}
3. 메인 클래스에 등록 (MyMod.java)
마지막으로 DeferredRegister들을 modEventBus에 등록.
// MyMod.java
TridentTempestZombieEntityTypeInit.ENTITY_TYPES.register(modEventBus);
TridentTempestZombieItemInit.ITEMS.register(modEventBus);
'모딩 > 마인크래프트 모드 개발 일지' 카테고리의 다른 글
| [마인크래프트 모딩]#15 상속이용및 기타 자잘한것들 수정 (15) | 2025.07.01 |
|---|---|
| [마인크래프트 모딩]#14 주변 아군에게 광역 버프를 주는 '좀비 지휘관' (9) | 2025.06.29 |
| [마인크래프트 모딩]#12 해골마 궁수 좀비 만들기 (8) | 2025.06.28 |
| [마인크래프트 모딩]#11 좀비힐러 (7) | 2025.06.28 |
| [마인크래프트 모딩]#10 모든 살아있는 생명을 공격하는 좀비 (4) | 2025.06.28 |