Newbie Spellweaver
- Joined
- Sep 11, 2016
- Messages
- 59
- Reaction score
- 81
Here's the 5th job V Matrix system packets and handlers. (Version 179).
Note that I have taken out code from massive functions in my source to give you just the related code, you will have to add them to wherever you handle or decide to handle the matrix related code.
OutPacket Opcodes
InPacket Opcodes
VMatrixRecord
WvsContext
OnPacket is where you handle functions based on what packet is received.
OnScriptItemUseRequest should be in UseScriptedItemHandler or a function in PlayerHandler
called UseScriptedItem or similar. Just add the case to your function / handler and adjust variable names.
OnUpdateMatrix you will probably add to a PlayerHandler or its own class (if you use a packet processor method)
Now for some things you are missing from these functions... Wherever you put your CharacterData, you will need these.
Note: You probably already do SkillRecord your own way so you will have to adjust the code to your method.
You will have to replace
with however you remove an item from your inventory.
You will have to replace the
with however you send a "Message" packet. I believe odin calls this SHOW_STATUS_INFO.
The MessageResult is SystemMessage aka 12.
You will have to replace
with however you send the ChangeStat Packet. I believe odin calls this packet updatePlayerStats or something similar.
You will have to replace
with however you send the UserEffectLocal packet, I believe odin has about 5000 packets for it, however it's part of 1 packet in a switch which looks like this. (Replace below with however you would do it)
Note: nUserEffect is Quest aka 8.
Now you also need to add a conditional near the bottom in SetField so your node matrix is updated when you migrate.
SetField (CharacterData::Encode Portion)
Note: This is very close to the bottom of the function, DBChar.WildHunterInfo is 0x200000 so just find that and place this in the conditonal. (It is below EquipExt and above CharacterPotentialSkill)
I don't know if I forgot anything, it took so long to write this and I believe I got everything. Anyway enjoy.
Note that I have taken out code from massive functions in my source to give you just the related code, you will have to add them to wherever you handle or decide to handle the matrix related code.
OutPacket Opcodes
PHP:
VMatrixUpdate(383)
NodeStoneResult(384)
InPacket Opcodes
PHP:
UserUpdateMatrix(569)
VMatrixRecord
PHP:
/**
*
* @author PacketBakery
*/
public class VMatrixRecord {
public int nState, nIconID, nSkillID, nSkillID2, nSkillID3, nSLV, nMasterLev, nRow, nExp;
public long dwCRC;
public FileTime ftExpirationDate = FileTime.GetPermanentTime();
public static int Disassembled = 0, Inactive = 1, Active = 2;
public void Encode(OutPacket oPacket) {
oPacket.EncodeLong(dwCRC);
oPacket.EncodeInt(this.nIconID);
oPacket.EncodeInt(this.nSLV);
oPacket.EncodeInt(this.nExp);
oPacket.EncodeInt(this.nState);
oPacket.EncodeInt(this.nSkillID);
oPacket.EncodeInt(this.nSkillID2);
oPacket.EncodeInt(this.nSkillID3);
oPacket.EncodeInt(this.ftExpirationDate.dwLowTime);
oPacket.EncodeInt(this.ftExpirationDate.dwHighTime);
}
}
WvsContext
PHP:
public static OutPacket OnVMatrixUpdate(List<VMatrixRecord> aVMatrixRecord, boolean bRemove) {
OutPacket oPacket = new OutPacket(LoopbackPacket.VMatrixUpdate);
oPacket.EncodeInt(aVMatrixRecord.size());
for (VMatrixRecord pMatrix : aVMatrixRecord) {
pMatrix.Encode(oPacket);
}
oPacket.EncodeBoolean(bRemove);
return oPacket;
}
public static OutPacket OnNodeStoneResult(int nItemID, int nSkillID1, int nSkillID2, int nSkillID3) {
OutPacket oPacket = new OutPacket(LoopbackPacket.NodeStoneResult);
oPacket.EncodeInt(nItemID);
oPacket.EncodeInt(1);
oPacket.EncodeInt(nSkillID1);
oPacket.EncodeInt(nSkillID2);
oPacket.EncodeInt(nSkillID3);
return oPacket;
}
OnPacket is where you handle functions based on what packet is received.
PHP:
public void OnPacket(final ClientPacket eType, final InPacket iPacket) {
switch (eType) {
case UserUpdateMatrix:
OnUpdateMatrix(iPacket);
break;
case UserScriptItemUseRequest:
OnScriptItemUseRequest(iPacket);
break;
}
}
OnScriptItemUseRequest should be in UseScriptedItemHandler or a function in PlayerHandler
called UseScriptedItem or similar. Just add the case to your function / handler and adjust variable names.
PHP:
public void OnScriptItemUseRequest(InPacket iPacket) {
int dwCRC = iPacket.DecodeInt();
short nSlot = iPacket.DecodeShort();
int nItemID = iPacket.DecodeInt();
int nCount = iPacket.DecodeInt();
switch(nItemID) {
case Consume.Nodestone: // ItemID: 2435902
VMatrixRecord pRecord = new VMatrixRecord();
pRecord.nState = VMatrixRecord.Inactive;
/*
* This is where you get to do work yourself.
* Write your own formula for what skills you want to gain by using the nodestone
* and set the variables in MatrixRecord
*/
this.GetCharacterData().aVMatrixRecord.add(pRecord);
SendPacket(WvsContext.OnNodeStoneResult(nItemID, pRecord.nSkillID, pRecord.nSkillID2, pRecord.nSkillID3);
this.GetCharacterData().RemoveItem(InventoryType.Consume, nSlot, nCount);
Message.Encode(new Message(MessageResult.SystemMessage, "You used the Nodestone and got a Core."));
SendCharacterStat(1, 0);
UserEffect.EncodeForLocal(new UserEffect(UserEffect.Quest, Consume.Nodestone));
break;
}
}
OnUpdateMatrix you will probably add to a PlayerHandler or its own class (if you use a packet processor method)
PHP:
public void OnUpdateMatrix(InPacket iPacket) {
int nState = iPacket.DecodeInt();
int nSlot = iPacket.DecodeInt();
int nNode = iPacket.DecodeInt();
VMatrixRecord pRecord = this.GetCharacterData().aVMatrixRecord.get(nSlot);
if (pRecord != null) {
if (nState == 1 || nState == 2) {
pRecord.nState = VMatrixRecord.Active;
} else if(nState == 3) {
pRecord.nState = VMatrixRecord.Disassembled;
}
if(pRecord.nState != VMatrixRecord.Active) {
this.GetCharacterData().mSkillRecord.remove(pRecord.nSkillID);
this.GetCharacterData().mSkillExpired.remove(pRecord.nSkillID);
this.GetCharacterData().mSkillMasterLev.remove(pRecord.nSkillID);
} else {
this.GetCharacterData().mSkillRecord.put(pRecord.nSkillID, pRecord.nSLV);
this.GetCharacterData().mSkillExpired.put(pRecord.nSkillID, pRecord.ftExpirationDate);
this.GetCharacterData().mSkillMasterLev.put(pRecord.nSkillID, pRecord.nMasterLev);
}
SendPacket(WvsContext.OnVMatrixUpdate(this.GetCharacterData().aVMatrixRecord, nState == 2 || nState == 3));
}
}
Now for some things you are missing from these functions... Wherever you put your CharacterData, you will need these.
Note: You probably already do SkillRecord your own way so you will have to adjust the code to your method.
PHP:
public List<VMatrixRecord> aVMatrixRecord = new ArrayList<>();
public Map<Integer, Integer> mSkillRecord = new HashMap<>();
public Map<Integer, Integer> mSkillExpired = new HashMap<>();
public Map<Integer, Integer> mSkillMasterLev = new HashMap<>();
You will have to replace
PHP:
this.GetCharacterData().RemoveItem(InventoryType.Consume, nSlot, nCount);
You will have to replace the
PHP:
Message.Encode(new Message(MessageResult.SystemMessage, "You used the Nodestone and got a Core."));
The MessageResult is SystemMessage aka 12.
You will have to replace
PHP:
SendCharacterStat(1, 0);
You will have to replace
PHP:
UserEffect.EncodeForLocal(new UserEffect(UserEffect.Quest, Consume.Nodestone));
Note: nUserEffect is Quest aka 8.
PHP:
public void EncodeForLocal() {
OutPacket oPacket = new OutPacket(LoopbackPacket.UserEffectLocal);
oPacket.EncodeByte(this.nUserEffect);
switch(this.nUserEffect) {
case Quest:
oPacket.EncodeByte(this.aQuestItem.size());
if(this.aQuestItem.size().isEmpty()) {
oPacket.EncodeString(this.sScrMsg);
oPacket.EncodeInt(this.nEffect);
} else {
for(ItemPickup pItem : this.aQuestItem) {
oPacket.EncodeInt(pItem.nItemID);
oPacket.EncodeInt(pItem.nAmount);
}
}
break;
}
}
Now you also need to add a conditional near the bottom in SetField so your node matrix is updated when you migrate.
SetField (CharacterData::Encode Portion)
Note: This is very close to the bottom of the function, DBChar.WildHunterInfo is 0x200000 so just find that and place this in the conditonal. (It is below EquipExt and above CharacterPotentialSkill)
PHP:
public void Encode(OutPacket oPacket, long dbCharFlag, boolean bBackwardUpdate) {
if ((dbCharFlag & DBChar.WildHunterInfo.Get()) > 0) {
oPacket.EncodeInt(this.aVMatrixRecord.size());
for (VMatrixRecord pRecord : this.aVMatrixRecord) {
pRecord.Encode(oPacket);
}
}
}
I don't know if I forgot anything, it took so long to write this and I believe I got everything. Anyway enjoy.
Last edited: