Jump to content

OtherChoice

Inactive Member
  • Posts

    91
  • Joined

  • Last visited

  • Days Won

    3
  • Feedback

    0%

Posts posted by OtherChoice

  1. Hello everyone I was wondering which is the best way to render a color pixel at given position on screen. No 3d vector to multiply by view matrix since i need to display it only on user screen at position (x coordinate, y coordinate). Resource(memory)-wise and by execution time what would you suggest me to do: using CGraphicImageInstance like minimap npcs and monsters, loading a 1px colored external image, python turtle module, or anything else which you think its a good choice? Thanks in advice.

  2. 2 hours ago, matyasvane said:

    Hey,

    I'm starting with the game server for this game and need some advice. Please help me :)

    1.  When I want to edit (temporarily) a map,weapons etc, for example, how do I do it?
    2.  Can you please recommend a client who will automatically patch? (i can buy it)
    3.  How do I update a server without unnecessarily long shutdown? Can I edit files while the server is on and then restart the server?
    4.  Can I ask for a good guide on how to install WorldEdit on Windows 10?
    5.  Looking for a CMS for Metin2 with an Offline Store (IS) is there any?

     

    Thank you,

    Matthew

    1. You should specific what do you mean by 'edit' and 'temporarily'. Many things can be modified including 3d elements, textures, values, mechanics. Basically anything you can and cannot see while playing. Some of those things can be changed during execution time through coding, like values, mechanics and loading different external files such as textures models and so on. The latters can only by created and modified by external programs (not during execution time) or by including a whole new system in client and/or server source (for example a Guild flag editor ingame).

    To have full access over game files you should learn how to code in the following languages: c++(client and server source), python(client root), lua(server-side quests), sql(database values) and probably also php, javascript, html5, css3 for a good website. There are also a few handy libraries to learn (and maybe update) if you want to deeply understand some nasty stuff around the source: namely boost and d3dx8, windows api and std (standard c++ library) are instead mandatory.

    Apart from coding you will need furthert knowledge to really get into every part of the game. This knowledge includes 3d modelling, existing plugins allow you to convert 3DS (3d studio) models in gr2 used by client, Texturing, i do prefer gimp but anything will work, Map creation, made insanely easier through WorldEditor, Effect creation, such as skill effects, projectiles, auras and so on also handled by WorldEditor.

    2. Build your own

    3. Usually server shutdown and restart won't take longer than a few minutes, downtime strictly depends on the operations you are performing while server is closed. You can edit the source codes and client files while server is up, compile them and then when ready replace the olders & restart server.

    4.World Editor is pretty easy to setup have a D partition or mount a folder inside C as D and then create a folder named "ymir_work", extract your WorldEditor version inside that folder and you should be good (WorldEditor has a weird bug with my laptop viewport so I have to decrease Windows Resizing and Layout option from 125% to 100% to correctly display the editor).

    5. Cannot help you here, I do not like CMS. If you do then make sure the one you choose is clean and flawless.

     

    • Love 1
  3. The problem was the far clip float value retrived in python application.cpp 

    if (!PERF_CHECKER_RENDER_GAME)
        {
            m_kRenderTargetManager.RenderBackgrounds();
            float fAspect=m_kWndMgr.GetAspect();
            float fFarClip=m_pyBackground.GetFarClip();

            m_pyGraphic.SetPerspective(30.0f, fAspect, 100.0, fFarClip);   <---- fFarClip was smaller than dragon model far prespective 

  4. Tried with penger camera and still nothing displays, while every other model is showed correctly at the right size (both wild dog 101 and tree boss 2307 are perfectly centered and resized).

    TraceError("Actor Height: %f, Model: %d", fHeight, index); in SelectModel returns
    0312 15:22:17197 :: Actor Height: 207.197571, Model: 2108 -----> for desert bandit
    0312 15:22:33305 :: Actor Height: 2172.499023, Model: 2291 ----> for fire dragon

    The model and its properties are all ok and still it can't render. Is there any limitation for 3d vectors size in the custom defined camera?

  5. UPDATE: After a while i discovered that if I set normal camera CAMERA_MAX_DISTANCE to something very large (10000000.0f) then zoom all the way out the model is rendered correctly

    zmiphg.png

    5e5mc3.png

    Hello everybody, I have some problem rendering fire_dragon (2291) with CxL RenderTarget

    . Checked with multiple break points and TraceError(s) and everything seems ok. The model itself is displayed correctly when spawned, and also tried with older/custom version of it. All this made me believe that something might be wrong in camera settings for such a big model, so i tweaked with fov, aspect, near, far and SetViewParams(eye, target, up) but I had no luck. Anyone knows why this specific model is not rendering?

  6. I noticed embedded ingame browser is compatibility mode IE 7 by default, looked aroud the net and it seems that there's not so much detailed information about it. The best way would be to get your hands on chromium or something like that, but its a rather time sinking activity and since internet explorer emulated version can be easily changed with a new registry key i opted toward this solution. However (apparently, I actually searched very few sites) it seems that noone has ever mentioned it thus I decided to share the know-how with you. If anyone is interested this is a very simple example (very raw i suggest to at very least modify it):

    In UserInterface.cpp before bool Main(HINSTANCE hInstance, LPSTR lpCmdLine)
    
    void SetInternetRegKey()
    {
    	LONG status;
    	HKEY hKey;
    
    	status = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION"), 0, KEY_ALL_ACCESS, &hKey);
    	if ((status == ERROR_SUCCESS) && (hKey != NULL))
    	{
    		DWORD standard = 11000;
    		DWORD version;
    		DWORD size = sizeof(version);
    		DWORD type = REG_DWORD;
    		status = RegQueryValueEx(hKey, TEXT("YOURCLIENTEXECUTABLEFILE.EXTENSION"), NULL, &type, (BYTE*)&version, &size);
    		if (status != ERROR_SUCCESS)
    		{
    			status = RegSetValueEx(hKey, TEXT("YOURCLIENTEXECUTABLEFILE.EXTENSION"), NULL, REG_DWORD, (BYTE*)&standard, sizeof(standard));
    			if (status != ERROR_SUCCESS)
    			{
    
    			}
    		}
    		RegCloseKey(hKey);
    	}
    }
    then in bool Main at the beginning add SetInternetRegKey();
    bool Main(HINSTANCE hInstance, LPSTR lpCmdLine)
    {
    	SetInternetRegKey();      <--------- here

    This will add a registry value for FEATURE_BROWSER_EMULATION (YOURCLIENTEXECUTABLEFILE.EXTENSION, 11000) which will tell browser to emulate IE 11 at the launch of the executable and only once. As I said above this is very raw and won't autodetect latest avaible IE and many other lacks which you can clearly see. All documentation about IE registry key for version/svcVersion can be found here https://support.microsoft.com/en-us/help/969393/information-about-internet-explorer-versions
    Do your homework (just a few hours i think) and you will have your nice and clean browser emulation to latest avaible IE version or use it as it is and have a poor compatibilty still working IE11 browser. Hope you find this useful, Have a nice day.

    • Metin2 Dev 8
    • Confused 1
    • Good 3
    • Love 15
  7. Show me  your ActorInstanceBattle.cpp i'll take a look too.
    However those has something worng probably

    void CActorInstance::__PushCircle(CActorInstance & rVictim)
    {
    	const TPixelPosition& c_rkPPosAtk=NEW_GetAtkPixelPositionRef();
    
    	D3DXVECTOR3 v3SrcPos(c_rkPPosAtk.x, -c_rkPPosAtk.y, c_rkPPosAtk.z);
    
    	const D3DXVECTOR3& c_rv3SrcPos = v3SrcPos;
    	const D3DXVECTOR3& c_rv3DstPos = rVictim.GetPosition();
    
    	D3DXVECTOR3 v3Direction;
    	v3Direction.x = c_rv3DstPos.x - c_rv3SrcPos.x;
    	v3Direction.y = c_rv3DstPos.y - c_rv3SrcPos.y;
    	v3Direction.z = 0.0f;
    	D3DXVec3Normalize(&v3Direction, &v3Direction);
    
    	rVictim.__SetFallingDirection(v3Direction.x, v3Direction.y);
    }
    
    void CActorInstance::__PushDirect(CActorInstance & rVictim)
    {
    	D3DXVECTOR3 v3Direction;
    	v3Direction.x = cosf(D3DXToRadian(m_fcurRotation + 270.0f));
    	v3Direction.y = sinf(D3DXToRadian(m_fcurRotation + 270.0f));
    	v3Direction.z = 0.0f;
    
    	rVictim.__SetFallingDirection(v3Direction.x, v3Direction.y);
    }

    Check for null vectors and __SetFallingDirection function

  8. Ok i checked the source and i was recalling pretty much everything but a dumb thing insted of 
     

    if (fDist < fMinDist || pkVictim->IsDead())
    	{
    		pkVictim = pAttacker;
    		fMinDist = fDist;
    	}

    Use this

     

    if (fDist < fMinDist && !pAttacker->IsDead())
    	{
    		pkVictim = pAttacker;
    		fMinDist = fDist;
    	}

    Tested and working. If you are willing to donate something i'll appreciate it, anyhow have a nice day!

  9. Hello everyone, I came across a really annoying problem and I hope you guys can help me. I need to change the structure of item_proto (/locale/lang/item_proto) to commit these changes:

        <ItemDef Vnum="" Name="'" LocalizedName="" Type="" SubType="" Weight="" Size="" AntiFlags="" Flags="" WearFlags="" ImmuneFlags="" Gold="" ShopBuyPrice="" LimitType0="" LimitValue0="" LimitType1="" LimitValue1="" ApplyType0="" ApplyValue0="" ApplyType1="" ApplyValue1="" ApplyType2="" ApplyValue2="" Value0="" Value1="" Value2="" Value3="" Value4="" Value5="" Socket0="" Socket1="" Socket2="" //add here//  Socket3="" Socket4="" Socket5="" //end// RefinedVnum="" RefineSet="" AlterToMagicItemPercent="" Specular="" GainSocketPercent="" AddonType=""  />

    Basically i need to add a entry for those sockets (3,4,5). Tools around the web to crypt/decrypt item_proto are very "standardized", they only work with a standard item_proto template hence packing only standard entries, and no open source code is avaible.  If you guys have any suggestion and/or solution I'll be very grateful. It seems that I was wrong i ended up solving the problem once I found this:

    This is the hidden content, please

    I wish to thank the respective owner.

    • Metin2 Dev 7
    • Good 2
    • Love 4
  10. Honestly i do not know why timed_event_cancel has no declaration however just go in game/battle.h, find 
    extern void    battle_end(LPCHARACTER ch); and add below 
    extern bool timed_event_cancel(LPCHARACTER ch);
    then check game/battle.cpp should contain this function
     

    bool timed_event_cancel(LPCHARACTER ch)
    {
    	if (ch->m_pkTimedEvent)
    	{
    		event_cancel(&ch->m_pkTimedEvent);
    		return true;
    	}
    	return false;
    }

    Now you should not have any compiling error.
    Next you asked about packets: input_main.cpp handles packets with HEADER_CG (CG == client to game) in function int CInputMain::Analyze(LPDESC d, BYTE bHeader, const char * c_pData).
    Packets with HEADER_GC (GC == game to client) are instead handled by the client itself but according to the phase the client is in (eg. phaseGame, phaseSelect...).
    phaseGame packets (which are most probably what are you looking for) are recived in Userinterface/PythonNetworkStreamPhaseGame.cpp  in void CPythonNetworkStream::GamePhase().
    Other Client Packet Reciever
     

    Spoiler

    bool CGuildMarkDownloader::__DispatchPacket(UINT header) //GuilMarkDownloader.cpp
    {
        switch (header)
        {
            case HEADER_GC_PHASE:
                return __LoginState_RecvPhase();
            case HEADER_GC_HANDSHAKE:
                return __LoginState_RecvHandshake();
            case HEADER_GC_PING:
                return __LoginState_RecvPing();
            case HEADER_GC_MARK_IDXLIST:
                return __LoginState_RecvMarkIndex();
            case HEADER_GC_MARK_BLOCK:
                return __LoginState_RecvMarkBlock();
            case HEADER_GC_GUILD_SYMBOL_DATA:
                return __LoginState_RecvSymbolData();
            case HEADER_GC_MARK_DIFF_DATA: 
                return true;
        }
        return false;    
    }

    void CPythonNetworkStream::LoginPhase() //UserInterface/PythonNetworkStreamPhaseLogin.cpp
    {
        TPacketHeader header;
        if (!CheckPacket(&header))
            return;

        switch (header)
        {
            case HEADER_GC_PHASE:
                if (RecvPhasePacket())
                    return;
                break;

            case HEADER_GC_LOGIN_SUCCESS3:
                if (__RecvLoginSuccessPacket3())
                    return;
                break;
            case HEADER_GC_LOGIN_SUCCESS4:
                if (__RecvLoginSuccessPacket4())
                    return;
                break;

    and so on (if you want to find em all go in visual studio CTRL+F -> find HEADER_GC -> in whole solution

    And lastly there are some HEADER_GD packets which are game to database handled by db binary.

  11. This is not how official logout works: in game/battle.cpp you have a function bool timed_event_cancel(LPCHARACTER ch) which checks whether the argument (LPCHARACTER ch) is logging off or not, if so it will cancel the timed event and return true. This function is called in int battle_melee_attack (LPCHARACTER ch, LPCHARACTER victim) on both victim and attacker and on a true (stopped logout attempt) will send chat_packet "the battle has begun..."
    If you want to stop logout on a custom defined action you can simply call timed_event_cancel(ch).

    • Love 1
  12. Check those things :
    1) item_proto table (serverside either txt or sql) and item_proto (client side) prices matches
    2) In PythonPlayerModule.cpp in PyObject * playerGetSellItemPrice(PyObject * poSelf, PyObject * poArgs) there's a line:   iPrice /= 5; and the same exact value should be set in shop_manager.cpp (server source/game) in void CShopManager::Sell(LPCHARACTER ch, BYTE bCell, BYTE bCount) like this:  dwPrice /= 5;  (If any of those two is missing or has a different value make sure to correct it).

    • Love 2
  13. Ok after testing the original bugfix you linked i found the problem, the m_akSimplePlayerInfo array is filled in a wrong way this is the solution:
    In game/char.cpp at void CHARACTER::PointsPacket() change as following
     

    void CHARACTER::PointsPacket()
    {
    	if (!GetDesc())
    		return;
    
    	TPacketGCPoints pack;
    
    	pack.header	= HEADER_GC_CHARACTER_POINTS;
    
    	pack.points[POINT_LEVEL]		= GetLevel();
    	pack.points[POINT_EXP]		= GetExp();
    	pack.points[POINT_NEXT_EXP]		= GetNextExp();
    	pack.points[POINT_HP]		= GetHP();
    	pack.points[POINT_MAX_HP]		= GetMaxHP();
    	pack.points[POINT_SP]		= GetSP();
    	pack.points[POINT_MAX_SP]		= GetMaxSP();
    	pack.points[POINT_GOLD]		= GetGold();
    	pack.points[POINT_STAMINA]		= GetStamina();
    	pack.points[POINT_MAX_STAMINA]	= GetMaxStamina();
    	for (int i = POINT_ST; i < POINT_IQ + 1; ++i)
    		pack.points[i] = GetRealPoint(i);
    	
    	for (int i = POINT_IQ + 1; i < POINT_MAX_NUM; ++i)
    		pack.points[i] = GetPoint(i);
    
    	GetDesc()->Packet(&pack, sizeof(TPacketGCPoints));
    }

    then at void CHARACTER::Disconnect add this line

    if (GetDesc())
    	{
      		/*add this*/
    		PointsPacket();
      		/*        */
      
    		packet_point_change pack;
    		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
    		pack.dwVID = m_vid;
    		pack.type = POINT_PLAYTIME;
    		pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
    		pack.amount = 0;
    		GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
    		GetDesc()->BindCharacter(NULL);
    //		BindDesc(NULL);
    	}

    then in client source

    PythonNetworkStreamPhaseGame.cpp -> bool CPythonNetworkStream::RecvPointChange()  ------->Make these changes
    
    case POINT_PLAYTIME:
    	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].dwPlayMinutes = PointChange.value;
    	break;
    case POINT_LEVEL:
    	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointChange.value;
    	__RefreshStatus();
    	__RefreshSkillWindow();
    	break;
    /*case POINT_ST:
    	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointChange.value;
    	__RefreshStatus();
    	__RefreshSkillWindow();
    	break;
    case POINT_DX:
    	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointChange.value;
    	__RefreshStatus();
    	__RefreshSkillWindow();
    	break;
    case POINT_HT:
    	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointChange.value;
    	__RefreshStatus();
    	__RefreshSkillWindow();
    	break;
    case POINT_IQ:
    	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointChange.value;
    	__RefreshStatus();
    	__RefreshSkillWindow();
    	break;*/
    case POINT_ST:
    case POINT_DX:
    case POINT_HT:
    case POINT_IQ:
    	__RefreshStatus();
    	__RefreshSkillWindow();
    break;

    Every other thing is like original thread 

    Quote

    What I did with the client and the packet set in Disconnect() came from this post:

    Tested and working.

    • Love 1
  14. Oh ok i quite didn't get it, anyhow that's the solution you are looking for
     

    This is you void CHARACTER::Disconnect(...)
    //ADD this
    PointChange(POINT_ST, 0);
    PointChange(POINT_DX, 0);
    PointChange(POINT_IQ, 0);
    PointChange(POINT_HT, 0);
    //end
    
    packet_point_change pack;
    pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
    pack.dwVID = m_vid;
    pack.type = POINT_PLAYTIME;
    pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
    pack.amount = 0;
    pack.point_ST = GetPoint(POINT_ST);
    pack.point_DX = GetPoint(POINT_DX);
    pack.point_HT = GetPoint(POINT_HT);
    pack.point_IQ = GetPoint(POINT_IQ);
    GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
    
    /*if (GetHorseST() > GetPoint(POINT_ST))
    	PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
    
    if (GetHorseDX() > GetPoint(POINT_DX))
    	PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));				REMOVE ALL THIS
    
    if (GetHorseHT() > GetPoint(POINT_HT))
    	PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
    
    if (GetHorseIQ() > GetPoint(POINT_IQ))
    	PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));*/ 

     

  15. The way you are trying to work with won't go anywhere, first, the point you are packing are in a wrong place, since the first time ComputePoints() is exectuted it will check whether your horse has higher stats than yours and then replace them if so and will however pack and send them to client. If you want to make sure you have your real stat points you need to create the packet inside CHARACTER::ComputePoints() function not in void CHARACTER::Disconnect. Next point is the packet you are using: since packet_point_change (HEADER_GC_CHARACTER_POINT_CHANGE) has already a defined behavior (it has 3 different behavior actually, in PhaseGame, PhaseSelect and PhaseLoading) i suggest you to avoid using it.
    Moreover if your goal is to always show base stats and hide horse bonuses, you can skip the whole client part and do in a simpler way.
    I will first explain how to get both base Stats and horse Stats.

    Spoiler

    I just tried the code i wrote and everything works fine. There's just a couple of thing i missed when answering

     

    Quote

    In Server source game/char.cpp in ComputePoints() 

    
    
    if (IsPC())
    	{
    		if (GetMountVnum()) 
    		{
    			if (GetHorseST() > GetPoint(POINT_ST))
    				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
    
    			if (GetHorseDX() > GetPoint(POINT_DX))
    				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));
    
    			if (GetHorseHT() > GetPoint(POINT_HT))
    				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
    
    			if (GetHorseIQ() > GetPoint(POINT_IQ))
    				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
    		}
    
    	}

    This way horse stats will override lower stats. Those numbers are then packeted and sent to client. You could create a new packet sending base stats to client. To recive base stats from game use game/char.cpp int CHARACTER::GetPoint(type) where type is POINT_ST, POINT_DX, POINT_HT, POINT_IQ example:

    
    
    game/packet.h && UserInterface/packet.h
      
      enum
    {
    	HEADER_CG_HANDSHAKE				= 0xdc,
      ....
        HEADER_GC_BASE_STATS			= (your_value),
      
      typedef struct base_stats
    {
    	BYTE	header;
    	DWORD	point_ST;
    	DWORD	point_DX;
    	DWORD	point_HT;
    	DWORD	point_IQ;
    } TPacketGCBaseStats;

     then send this packet from somewhere:
     

    
    
    game/char.cpp ComputePoints()
    if (IsPC())
    	{
    		if (GetMountVnum()) 
    		{
    			TPacketGCBaseStats pack;
    			pack.header = HEADER_GC_BASE_STATS;
    			pack.point_ST = GetPoint(POINT_ST);
    			pack.point_DX = GetPoint(POINT_DX);
    			pack.point_HT = GetPoint(POINT_HT);
    			pack.point_IQ = GetPoint(POINT_IQ);
    			ch->GetDesc()->Packet(&pack, sizeof(pack));
    			if (GetHorseST() > GetPoint(POINT_ST))
    				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
    
    			if (GetHorseDX() > GetPoint(POINT_DX))
    				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));
    
    			if (GetHorseHT() > GetPoint(POINT_HT))
    				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
    
    			if (GetHorseIQ() > GetPoint(POINT_IQ))
    				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
    		}

    Before TPacketGCBaseStats pack add this:

    ...
    PointChange(POINT_ST, 0);
    PointChange(POINT_DX, 0);
    PointChange(POINT_IQ, 0);
    PointChange(POINT_HT, 0);
    TPacketGCBaseStats pack;
    pack.header = HEADER_GC_BASE_STATS;
    ...

    then in PythonNetworkStreamPhaseGame.cpp:

    
    void CPythonNetworkStream::GamePhase()
    {
    	...
    	switch (header)
    		{
    			case HEADER_GC_OBSERVER_ADD:
    				ret = RecvObserverAddPacket();
    				break;
        		....
    			case HEADER_GC_BASE_STATS:
    				ret = RecvBaseStatsPacket();
    					break;
      		}
    }
    
    then after
    bool CPythonNetworkStream::RecvPointChange()
    {
      ...
    }
    add
    bool CPythonNetworkStream::RecvBaseStatsPacket()
    {
      TPacketGCBaseStats pack;
      if (!Recv(sizeof(TPacketGCBaseStats), &pack))
    	{
    		Tracen("Recv Base Stats Packet Error");
    		return false;
    	}
      //here you can do whatever you like with those number, to make sure you everything runs smoothly you can try this
      TraceError("Point_ST = %d, Point_DX =  %d, Point_HT = %d, Point_IQ = %d \n", pack.point_ST, pack.point_DX, pack.POINT_HT, pack.point_IQ);
      // so you can run your client then check syserr.txt and look at the output
    }
    
    and in PythonNetworkStream.h after
      bool RecvPointChange();
    add
      bool RecvBaseStatsPacket();

     

    ____________________________________________________________________________________________________

    If you want to totally hide horse stats you can do something like this:

    Spoiler

     

    in char.cpp change void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast) to 

    void CHARACTER::PointChange(BYTE type, int amount, int baseAmount=0, bool bAmount, bool bBroadcast) and change the definition in char.h as well (without =0 in the header file)

    then at the end of the function you will find 

    
    if (GetDesc())
    	{
    		struct packet_point_change pack;
    
    		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
    		pack.dwVID = m_vid;
    		pack.type = type;
    		pack.value = val;
    
    		if (bAmount)
    			pack.amount = amount;
    		else
    			pack.amount = 0;
    
    		if (!bBroadcast)
    			GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
    		else
    			PacketAround(&pack, sizeof(pack));
    	}
    }
    
    and change it like this
    
    if (GetDesc())
    	{
    		struct packet_point_change pack;
    
    		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
    		pack.dwVID = m_vid;
    		pack.type = type;
    		pack.value = baseAmount ? baseAmount : val;
    
    		if (bAmount)
    			pack.amount = amount;
    		else
    			pack.amount = 0;
    
    		if (!bBroadcast)
    			GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
    		else
    			PacketAround(&pack, sizeof(pack));
    	}
    }
    
    Lastly  you need to edit char.cpp void CHARACTER::ComputePoints()
    find
    if (GetMountVnum()) 
    		{
    			if (GetHorseST() > GetPoint(POINT_ST))
    				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
    
    			if (GetHorseDX() > GetPoint(POINT_DX))
    				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));
    
    			if (GetHorseHT() > GetPoint(POINT_HT))
    				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
    
    			if (GetHorseIQ() > GetPoint(POINT_IQ))
    				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
    		}
    
    and change it like this
    
    if (GetMountVnum()) 
    		{
    			if (GetHorseST() > GetPoint(POINT_ST))
    				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), GetPoint(POINT_ST));
    
    			if (GetHorseDX() > GetPoint(POINT_DX))
    				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), GetPoint(POINT_DX));
    
    			if (GetHorseHT() > GetPoint(POINT_HT))
    				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), GetPoint(POINT_HT));
    
    			if (GetHorseIQ() > GetPoint(POINT_IQ))
    				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), GetPoint(POINT_IQ));
    		}

     

     

    Done.

  16. In Server source game/char.cpp in ComputePoints() 

    if (IsPC())
    	{
    		if (GetMountVnum()) 
    		{
    			if (GetHorseST() > GetPoint(POINT_ST))
    				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
    
    			if (GetHorseDX() > GetPoint(POINT_DX))
    				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));
    
    			if (GetHorseHT() > GetPoint(POINT_HT))
    				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
    
    			if (GetHorseIQ() > GetPoint(POINT_IQ))
    				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
    		}
    
    	}

    This way horse stats will override lower stats. Those numbers are then packeted and sent to client. You could create a new packet sending base stats to client. To recive base stats from game use game/char.cpp int CHARACTER::GetPoint(type) where type is POINT_ST, POINT_DX, POINT_HT, POINT_IQ example:

    game/packet.h && UserInterface/packet.h
      
      enum
    {
    	HEADER_CG_HANDSHAKE				= 0xdc,
      ....
        HEADER_GC_BASE_STATS			= (your_value),
      
      typedef struct base_stats
    {
    	BYTE	header;
    	DWORD	point_ST;
    	DWORD	point_DX;
    	DWORD	point_HT;
    	DWORD	point_IQ;
    } TPacketGCBaseStats;

     then send this packet from somewhere:
     

    if (IsPC())
    	{
    		if (GetMountVnum()) 
    		{
    			TPacketGCBaseStats pack;
    			pack.header = HEADER_GC_BASE_STATS;
    			pack.point_ST = GetPoint(POINT_ST);
    			pack.point_DX = GetPoint(POINT_DX);
    			pack.point_HT = GetPoint(POINT_HT);
    			pack.point_IQ = GetPoint(POINT_IQ);
    			ch->GetDesc()->Packet(&pack, sizeof(pack));
    			if (GetHorseST() > GetPoint(POINT_ST))
    				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));
    
    			if (GetHorseDX() > GetPoint(POINT_DX))
    				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));
    
    			if (GetHorseHT() > GetPoint(POINT_HT))
    				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));
    
    			if (GetHorseIQ() > GetPoint(POINT_IQ))
    				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
    		}

    And then recive it from client and do whatever you like with those.

    REMEMBER to declare both the packet header and the typedef struct inside packet.h of client binary as well.

×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.