사이트 로그인
2022.11.17 15:40
조건
1. 유저 커멘드가 활성화 되어있어야 한다. (이거까지는 구현해주셔야 해요)
2. 사용하시는 소스와 스타일에 따라 다름으로 어느정도 이해가 있으신 경우에만 사용하여 주세요.
2.7 버전 순정 버전 기준에서 테스트 완료된 소스 입니다.
3. 저같은 경우 고대의 강력 체력회복제로 해두었는데 변경하고 싶다면 아이템 아이디 부분만 자신의 데이터베이스에서 확인하여 고치시면 되겟죠? ㅎㅎ
------------------------------------------------------
사용법
95%미만인 경우 물약 사용 : .자동물약 켬 95
자동물약사용 끔: .자동물약 끔
유의점
자동물약이 켜져있는 상태에서 물약이 모두 소진되면 소진된 메세지와 함께 소진상태로 변경
이후 귀환하여 물약만 구매하면 바로 자동 사용처리 (리스 or 끔 이전까지 유지)
------------------------------------------------------
1. UserCommands.java [사용자 명령어 처리]
※ 저같은 경우 cmd를 else if 문에서 switch 문으로 바꾸었습니다. switch(cmd) { case "자동물약": toAutoPotion(pc, param); break; }
---------- or ------------------
else if (cmd.equalsIgnoreCase("자동물약") { toAutoPotion(pc, param); } |
1-2. toAutoPotion 함수 추가 [해당 부분은 게시판의 자동물약 소스올려주신분꺼 참고 하여 수정하여 올렸습니다.]
static private void toAutoPotion(L1PcInstance pc, String st) throws Exception { try { String[] params = st.split("\\s"); // System.out.println(Arrays.toString(params)); switch(params[0]) { case "켬": if(params.length < 2) { pc.sendPackets(new S_SystemMessage("자동물약 설정한 HP %를 입력하여주세요.")); return; } int rate = Integer.parseInt(params[1]); if(rate < 0 || rate > 100) { pc.sendPackets(new S_SystemMessage("자동물약 범위는 0~100 사이로 설정하여 주세요.")); return; } pc.setIsAutoPotion(true); pc.setAutoPotionPercent(rate); pc.sendPackets(new S_SystemMessage("현재 HP가 " + params[1] + "% 이하이면 고대의 강력 체력 회복제를 자동으로 사용합니다.")); break; case "끔": pc.setIsAutoPotion(false); pc.setAutoPotionPercent(0); pc.sendPackets(new S_SystemMessage("자동물약을 비활성화 합니다.")); break; default: pc.sendPackets(new S_SystemMessage(".자동물약 [켬/끔] [0~100] ex: .자동물약 켬 95, .자동물약 끔")); break; }
} catch(Exception ex) { pc.sendPackets(new S_SystemMessage(".자동물약 [켬/끔] [0~100] ex: .자동물약 켬 95, .자동물약 끔")); } } |
☆ 여기까지 오셨다면 pc.setIsAutoPotion, pc.setAutoPotionPercent 두가지 함수가 오류가 나있을텐데 해당 부분을 추가하도록 합니다.
2. L1PcInstance.java 수정
private boolean _isAutoPostion; //현재 케릭터의 자동포션 설정상태 true : 켬, false: 끔 public boolean getIsAutoPotion() { return this._isAutoPostion; } public void setIsAutoPotion(boolean isAutoPostion) { this._isAutoPostion = isAutoPostion; }
private int _autoPotionPercent; //현재 케릭터의 자동포션 기준 잔량(몇%미만일때 실행할지) public int AutoPotionPercent() { return this._autoPotionPercent; } public void setAutoPotionPercent(int autoPotionPercent) { this._autoPotionPercent = autoPotionPercent; }
private boolean _postionChecker; // 포션을 가지고 있는지? public boolean postionChecker() { return this._postionChecker; } public void setPostionChecker(boolean postionChecker) { if(_postionChecker && !postionChecker) { // True에서 False로 변경시 에러 메세지 출력 sendPackets(new S_SystemMessage("고대의 강력 체력 회복제가 모두 소진되었습니다.")); } this._postionChecker = postionChecker; } |
★ 자 이제 여기까지 설정이되었다면 기본적인 설정이 모두 완료 되었습니다.
-> 이제 매초당 실행을 해야하겟죠? 하지만 우리 2.7에는 매초마다 실행시키는 부분이 없습니다... 마땅한게 없어서 찾아보려다가 앞으로 기능추가를 위해 파일을 생성합니다.
~~.server.server 패키지에 클래스 추가
3. CharacterTimeController.java
package l1j.server.server;
import static l1j.server.server.model.skill.L1SkillId.ABSOLUTE_BARRIER; import static l1j.server.server.model.skill.L1SkillId.POLLUTE_WATER;
import java.sql.Timestamp; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger;
import l1j.server.server.model.L1ItemDelay; import l1j.server.server.model.L1PcInventory; import l1j.server.server.model.L1World; import l1j.server.server.model.Instance.L1ItemInstance; import l1j.server.server.model.Instance.L1PcInstance; import l1j.server.server.serverpackets.S_ServerMessage; import l1j.server.server.serverpackets.S_SkillSound; import l1j.server.server.serverpackets.S_SystemMessage;
public class CharacterTimeController implements Runnable{ private static Logger _log = Logger.getLogger(CharacterTimeController.class.getName());
private static CharacterTimeController _instance; private static Random _random = new Random();
public static CharacterTimeController getInstance() { if (_instance == null) { _instance = new CharacterTimeController(); } return _instance; }
@Override public void run() { try { while (true) { autoPostionChecker(); // 자동 포션기능 체크 Thread.sleep(1000); //1 초당 설정 } } catch (Exception e1) { System.out.println(CharacterTimeController.class.getName() + " [Error] " + e1.getMessage()); } }
private static void autoPostionChecker() { try { for (L1PcInstance pc : L1World.getInstance().getAllPlayers()) { boolean isStorePostion = pc.getInventory().checkItem(40024); //고대의 강력 체력 회복제(40024) 체크 pc.setPostionChecker(isStorePostion); // System.out.println(pc.getAccountName() + " 자동물약: " + pc.getIsAutoPotion() + pc.AutoPotionPercent() + isStorePostion);
// 죽은 상태면 포션을 먹지 않는다. if(pc.isDead()) { return; } if (pc.isTeleport()) { // 텔레포트 처리중 return; } // 오토포션이 설정안되어 있다면 종료한다. if(!pc.getIsAutoPotion()) { return; }
float nowHPPercent = ((float)pc.getCurrentHp() / (float)pc.getMaxHp()) * 100; float rate = pc.AutoPotionPercent(); // System.out.println(pc.getName() + "HP [ " + nowHPPercent + " / " + rate + " ]"); if(pc.getIsAutoPotion()) { // 자동포션이 설정된 유저만 동작 if(pc.postionChecker()) { // 포션이 존재하는 경우에만 로직을 동작 if(nowHPPercent < rate) { L1ItemInstance autoPostionItem = pc.getInventory().findItemId(40024); // 아이템 아이디 // System.out.println(autoPostionItem); if(autoPostionItem != null) { UseHeallingPotion(pc, 55, 197); pc.getInventory().removeItem(autoPostionItem, 1); pc.saveInventory(); L1ItemDelay.onItemUse(pc.getNetConnection(), autoPostionItem); // 아이템 지연 개시 } } } } } } catch(Exception e) { System.out.println("CTimeController-autoPostionChecker [Error] : " + e.getMessage()); }
}
private static void UseHeallingPotion(L1PcInstance pc, int healHp, int gfxid) { if (pc.hasSkillEffect(71) == true) { // 디케이포션 상태 pc.sendPackets(new S_ServerMessage(698)); // 마력에 의해 아무것도 마실 수가 없습니다. return; } // 아브소르트바리아의 해제 cancelAbsoluteBarrier(pc);
pc.sendPackets(new S_SkillSound(pc.getId(), gfxid)); pc.broadcastPacket(new S_SkillSound(pc.getId(), gfxid)); pc.sendPackets(new S_ServerMessage(77)); // \f1기분이 좋아졌습니다. healHp *= (_random.nextGaussian() / 5.0D) + 1.0D; if (pc.hasSkillEffect(POLLUTE_WATER)) { // 포르트워타중은 회복량1/2배 healHp /= 2; } pc.setCurrentHp(pc.getCurrentHp() + healHp); }
private static void cancelAbsoluteBarrier(L1PcInstance pc) { // 아브소르트바리아의 해제 if (pc.hasSkillEffect(ABSOLUTE_BARRIER)) { pc.killSkillEffectTimer(ABSOLUTE_BARRIER); pc.startHpRegeneration(); pc.startMpRegeneration(); pc.startMpRegenerationByDoll(); } } } |
※ 아직 고칠께 많지만.. 이제 마지막 설정
4. GameServer.java 두줄 추가!
※ 프리미엄타임컨트롤이 있다면 그 아래 선언 해주시면 좋을꺼 같아요!
CharacterTimeController characterTimeController = CharacterTimeController.getInstance(); GeneralThreadPool.getInstance().execute(characterTimeController); |
기본적인 구현만 된 상태이며 아직 예외나 많은 테스트가 부족합니다.
그냥 복사 붙여넣기식 구현보다는 각각의 함수가 무엇을 뜻하며 파일이 뭘뜻하는지 이해를 하시고 사용하셔야 더욱더 재미있게 즐길수 있을듯합니다!
좋은 정보 감사합니다