seemsq8 3 Report post Posted September 4, 2020 (edited) Hello, I have been working in a project recently using UE4, and I was wondering if someone can help me with the stats calculations. There are five primary attributes in our lovely game, which are "Strength, Accuracy, Spirit, Agility, and Constitution". in which, -Strength increases the attack of melee classes. -Agility increases Attack Speed and Dodge -Spirit increases SP, SP Recovery Rate and healing/damage dealt from Magic Skills. -Constitution increases HP, HP Recovery Rate and Defense. -Accuracy increases Hit Rate and the attack of ranged classes. The questions are, -how much max/min attack does a single strength point add? whats the formula behind it? -how much attack speed & dodge do we get from adding a single point in agility? -etc.. you get the idea! Thank you! Edited September 4, 2020 by seemsq8 Quote Share this post Link to post Share on other sites
seemsq8 3 Report post Posted September 4, 2020 (edited) in case your wondering at what state i am at right now, Stats are implemented & replicated for multiplayer usages, but calculations are not accurate by all means. I just need the formulas to tweak em up real quick~ Edited September 4, 2020 by seemsq8 Quote Share this post Link to post Share on other sites
Perseus 98 Report post Posted September 4, 2020 I haven't touched this in a bit, but the calculated stats (max atk, hp) have different scaling per class. You can find the scalings and the final attribute calculation in AttrCalculate.lua, code like this - Mxhp_con_rad1[JOB_TYPE_XINSHOU], Mxhp_con_rad2[JOB_TYPE_XINSHOU], Mxhp_lv_rad[JOB_TYPE_XINSHOU] = 3 , 2 , 15 --���hp������Ӱ��ϵ��������ϵ�����ȼ�ϵ���������� Mxsp_sta_rad1[JOB_TYPE_XINSHOU], Mxsp_sta_rad2[JOB_TYPE_XINSHOU], Mxsp_lv_rad[JOB_TYPE_XINSHOU] = 1 , 0 , 3 --���sp������Ӱ��ϵ��������ϵ��������ϵ�����ȼ�ϵ�� Mnatk_str_rad1[JOB_TYPE_XINSHOU], Mnatk_str_rad2[JOB_TYPE_XINSHOU], Mnatk_dex_rad1[JOB_TYPE_XINSHOU], Mnatk_dex_rad2[JOB_TYPE_XINSHOU] = 1.5 , 0.4 , 0 , 0 --��С������������Ӱ��ϵ��������ϵ�� Mxatk_str_rad1[JOB_TYPE_XINSHOU], Mxatk_str_rad2[JOB_TYPE_XINSHOU], Mxatk_dex_rad1[JOB_TYPE_XINSHOU], Mxatk_dex_rad2[JOB_TYPE_XINSHOU] = 1.5 , 0.4 , 0 , 0 --���������Ӱ��ϵ��������ϵ�� Def_con_rad1[JOB_TYPE_XINSHOU], Def_con_rad2[JOB_TYPE_XINSHOU] = 0.1 , 0.1 --����������Ӱ��ϵ����רעϵ�� Hit_dex_rad1[JOB_TYPE_XINSHOU], Hit_dex_rad2[JOB_TYPE_XINSHOU] = 0.6 , 0 --���е�����Ӱ��ϵ����רעϵ�����ȼ�ϵ������С������ Flee_agi_rad1[JOB_TYPE_XINSHOU], Flee_agi_rad2[JOB_TYPE_XINSHOU] = 0.6 , 0 --���ܵ�����Ӱ��ϵ��������ϵ�����ȼ�ϵ������С������ Mf_luk_rad[JOB_TYPE_XINSHOU] = 0.39 --�����ʵ�����Ӱ��ϵ��������ϵ�� Crt_luk_rad[JOB_TYPE_XINSHOU] = 0.31 --����������Ӱ��ϵ��������ϵ������С�����ʡ������ Hrec_bsmxhp_rad[JOB_TYPE_XINSHOU], Hrec_con_rad[JOB_TYPE_XINSHOU] = 1/200 , 1/8 --hp�ظ�������Ӱ��ϵ�������hpϵ�����ȼ�ϵ����hp��С�ظ��ٶ� Srec_bsmxsp_rad[JOB_TYPE_XINSHOU], Srec_sta_rad[JOB_TYPE_XINSHOU] = 1/100 , 1/12 --sp�ظ�������Ӱ��ϵ�������spϵ�����ȼ�ϵ����sp��С�ظ��ٶ� Aspd_agi_rad[JOB_TYPE_XINSHOU] = 1.1 --����Ƶ�ʵ�����Ӱ��ϵ������������������ϵ������С����Ƶ�� -- Str_updata[JOB_TYPE_XINSHOU] = 0.2 Dex_updata[JOB_TYPE_XINSHOU] = 0.1 Con_updata[JOB_TYPE_XINSHOU] = 0.6 Agi_updata[JOB_TYPE_XINSHOU] = 0.1 Sta_updata[JOB_TYPE_XINSHOU] = 0.1 Luk_updata[JOB_TYPE_XINSHOU] = 0.1 shows the scaling for that job and you can see the final calculations in the `ExAttrCheck` function - local mxhp = math.floor(Con(role)*3 * Mxhp_con_rad1[job] + Mxhp_con_rad2[job] * math.pow( math.floor(Con(role)*3/20 ), 2) +Lv(role) * Mxhp_lv_rad[job] + 40) --[[�������mxhp]]-- local mxsp = math.floor(Sta(role)*3 * Mxsp_sta_rad1[job] + Mxsp_sta_rad2[job] * math.pow( math.floor(Sta(role)*3/20), 2) +Lv(role) * Mxsp_lv_rad[job] + 5) --[[�������mxsp]]-- local mnatk = math.floor( 0+ Str(role) * Mnatk_str_rad1[job] + Dex(role) * Mnatk_dex_rad1[job] + Mnatk_str_rad2[job] * math.pow(math.floor( Str(role)*4/20), 2 ) + Mnatk_dex_rad2[job] * math.pow(math.floor( Dex(role)*4/20), 2 ) ) --[[�������mnatk]]-- local mxatk = math.floor( 0+ Str(role) * Mxatk_str_rad1[job] + Dex(role) * Mxatk_dex_rad1[job] + Mxatk_str_rad2[job] * math.pow(math.floor( Str(role)*4/20), 2 ) + Mxatk_dex_rad2[job] * math.pow(math.floor( Dex(role)*4/20), 2 ) ) --[[�������mxatk]]-- local def = math.floor( Con(role)* 5 * Def_con_rad1[job] + Def_con_rad2[job] * math.floor( math.pow( Con(role) * 3 /20, 2) ) ) --[[�������def]]-- local hit = math.floor( Dex(role) * Hit_dex_rad1[job]) + Lv(role) * 2 + 5 --[[�������hit]]-- local flee = math.floor( Agi(role) * Flee_agi_rad1[job] ) + Lv(role) * 2 + 5 --[[�������flee]]-- local mf = 100 + math.floor( Luk(role)*3 * Mf_luk_rad[job] ) --[[�������mf]]-- local crt =11 + math.floor( Luk(role)*3 * Crt_luk_rad[job] ) --[[�������crt]]-- local hrec = math.max(math.max ( 2 * mxhp * Hrec_bsmxhp_rad[job] + Con(role)*3 * Hrec_con_rad[job] , 1) ,0) --[[�������hrec]]-- local srec = math.max((mxsp * Srec_bsmxsp_rad[job] + Sta(role)*3 * Srec_sta_rad[job])/2 , 1 ) --[[�������srec]]-- local aspd = math.floor ( 100000/ (math.min ( math.floor( 65 + Agi(role) * Aspd_agi_rad[job] ) , 300 ) ) ) --[[�������aspd]]-- Quote Share this post Link to post Share on other sites
seemsq8 3 Report post Posted September 4, 2020 3 minutes ago, Perseus said: I haven't touched this in a bit, but the calculated stats (max atk, hp) have different scaling per class. You can find the scalings and the final attribute calculation in AttrCalculate.lua, code like this - Mxhp_con_rad1[JOB_TYPE_XINSHOU], Mxhp_con_rad2[JOB_TYPE_XINSHOU], Mxhp_lv_rad[JOB_TYPE_XINSHOU] = 3 , 2 , 15 --���hp������Ӱ��ϵ��������ϵ�����ȼ�ϵ���������� Mxsp_sta_rad1[JOB_TYPE_XINSHOU], Mxsp_sta_rad2[JOB_TYPE_XINSHOU], Mxsp_lv_rad[JOB_TYPE_XINSHOU] = 1 , 0 , 3 --���sp������Ӱ��ϵ��������ϵ��������ϵ�����ȼ�ϵ�� Mnatk_str_rad1[JOB_TYPE_XINSHOU], Mnatk_str_rad2[JOB_TYPE_XINSHOU], Mnatk_dex_rad1[JOB_TYPE_XINSHOU], Mnatk_dex_rad2[JOB_TYPE_XINSHOU] = 1.5 , 0.4 , 0 , 0 --��С������������Ӱ��ϵ��������ϵ�� Mxatk_str_rad1[JOB_TYPE_XINSHOU], Mxatk_str_rad2[JOB_TYPE_XINSHOU], Mxatk_dex_rad1[JOB_TYPE_XINSHOU], Mxatk_dex_rad2[JOB_TYPE_XINSHOU] = 1.5 , 0.4 , 0 , 0 --���������Ӱ��ϵ��������ϵ�� Def_con_rad1[JOB_TYPE_XINSHOU], Def_con_rad2[JOB_TYPE_XINSHOU] = 0.1 , 0.1 --����������Ӱ��ϵ����רעϵ�� Hit_dex_rad1[JOB_TYPE_XINSHOU], Hit_dex_rad2[JOB_TYPE_XINSHOU] = 0.6 , 0 --���е�����Ӱ��ϵ����רעϵ�����ȼ�ϵ������С������ Flee_agi_rad1[JOB_TYPE_XINSHOU], Flee_agi_rad2[JOB_TYPE_XINSHOU] = 0.6 , 0 --���ܵ�����Ӱ��ϵ��������ϵ�����ȼ�ϵ������С������ Mf_luk_rad[JOB_TYPE_XINSHOU] = 0.39 --�����ʵ�����Ӱ��ϵ��������ϵ�� Crt_luk_rad[JOB_TYPE_XINSHOU] = 0.31 --����������Ӱ��ϵ��������ϵ������С�����ʡ������ Hrec_bsmxhp_rad[JOB_TYPE_XINSHOU], Hrec_con_rad[JOB_TYPE_XINSHOU] = 1/200 , 1/8 --hp�ظ�������Ӱ��ϵ�������hpϵ�����ȼ�ϵ����hp��С�ظ��ٶ� Srec_bsmxsp_rad[JOB_TYPE_XINSHOU], Srec_sta_rad[JOB_TYPE_XINSHOU] = 1/100 , 1/12 --sp�ظ�������Ӱ��ϵ�������spϵ�����ȼ�ϵ����sp��С�ظ��ٶ� Aspd_agi_rad[JOB_TYPE_XINSHOU] = 1.1 --����Ƶ�ʵ�����Ӱ��ϵ������������������ϵ������С����Ƶ�� -- Str_updata[JOB_TYPE_XINSHOU] = 0.2 Dex_updata[JOB_TYPE_XINSHOU] = 0.1 Con_updata[JOB_TYPE_XINSHOU] = 0.6 Agi_updata[JOB_TYPE_XINSHOU] = 0.1 Sta_updata[JOB_TYPE_XINSHOU] = 0.1 Luk_updata[JOB_TYPE_XINSHOU] = 0.1 shows the scaling for that job and you can see the final calculations in the `ExAttrCheck` function - local mxhp = math.floor(Con(role)*3 * Mxhp_con_rad1[job] + Mxhp_con_rad2[job] * math.pow( math.floor(Con(role)*3/20 ), 2) +Lv(role) * Mxhp_lv_rad[job] + 40) --[[�������mxhp]]-- local mxsp = math.floor(Sta(role)*3 * Mxsp_sta_rad1[job] + Mxsp_sta_rad2[job] * math.pow( math.floor(Sta(role)*3/20), 2) +Lv(role) * Mxsp_lv_rad[job] + 5) --[[�������mxsp]]-- local mnatk = math.floor( 0+ Str(role) * Mnatk_str_rad1[job] + Dex(role) * Mnatk_dex_rad1[job] + Mnatk_str_rad2[job] * math.pow(math.floor( Str(role)*4/20), 2 ) + Mnatk_dex_rad2[job] * math.pow(math.floor( Dex(role)*4/20), 2 ) ) --[[�������mnatk]]-- local mxatk = math.floor( 0+ Str(role) * Mxatk_str_rad1[job] + Dex(role) * Mxatk_dex_rad1[job] + Mxatk_str_rad2[job] * math.pow(math.floor( Str(role)*4/20), 2 ) + Mxatk_dex_rad2[job] * math.pow(math.floor( Dex(role)*4/20), 2 ) ) --[[�������mxatk]]-- local def = math.floor( Con(role)* 5 * Def_con_rad1[job] + Def_con_rad2[job] * math.floor( math.pow( Con(role) * 3 /20, 2) ) ) --[[�������def]]-- local hit = math.floor( Dex(role) * Hit_dex_rad1[job]) + Lv(role) * 2 + 5 --[[�������hit]]-- local flee = math.floor( Agi(role) * Flee_agi_rad1[job] ) + Lv(role) * 2 + 5 --[[�������flee]]-- local mf = 100 + math.floor( Luk(role)*3 * Mf_luk_rad[job] ) --[[�������mf]]-- local crt =11 + math.floor( Luk(role)*3 * Crt_luk_rad[job] ) --[[�������crt]]-- local hrec = math.max(math.max ( 2 * mxhp * Hrec_bsmxhp_rad[job] + Con(role)*3 * Hrec_con_rad[job] , 1) ,0) --[[�������hrec]]-- local srec = math.max((mxsp * Srec_bsmxsp_rad[job] + Sta(role)*3 * Srec_sta_rad[job])/2 , 1 ) --[[�������srec]]-- local aspd = math.floor ( 100000/ (math.min ( math.floor( 65 + Agi(role) * Aspd_agi_rad[job] ) , 300 ) ) ) --[[�������aspd]]-- Thank you!! Quote Share this post Link to post Share on other sites