User:Illviljan: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
>Illviljan
No edit summary
>Illviljan
mNo edit summary
 
(30 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{SMW generic stat table
==Subpages==
| end_index    = 3
{{Subpages}}
| stat1_id    = normal_elemental_damage_resistance_%
| stat1_value  = 16
| stat1_text  = 16% to all elemental resistances in Normal difficulty
| stat2_id    = cruel_elemental_damage_resistance_%
| stat2_value  = 26
| stat2_text  = 26% to all elemental resistances in Cruel difficulty
| stat3_id    = merciless_elemental_damage_resistance_%
| stat3_value  = 37
| stat3_text  = 37% to all elemental resistances in Merciless difficulty
}}


{{#ask:  
==Todo list==
[[-Has subobject::{{FULLPAGENAME}}]]
* Align passive skill tables with {{tlx|Item table}} by adding the parameters to pages using them:
[[Has stat id::~*normal_elemental_damage_resistance_%]]
** [[Template:Query ascendancy passive skills]]
|?Has stat value=
** [[Template:Query base passive skills]]
|format=ol
** [[Template:Query keystone passive skills]]
|sort=Has stat text
** [[Template:Query passive skills]]
|mainlabel=-
* Add option to remove column in item table if it's completely empty, relevant for {{tlx|Area item drops}}.
}}


{{abbr|{{c|diffnormal|{{#ask: [[-Has subobject::{{FULLPAGENAME}}]] [[Has stat id::~*normal_elemental_damage_resistance_%]]|?Has stat value=|mainlabel=-}} }}
==Scripts==
|{{#ask:[[-Has subobject::{{FULLPAGENAME}}]] [[Has stat id::~*normal_elemental_damage_resistance_%]] |?Has stat text= |mainlabel=-}} }}
{{cot|Matlab scripts}}
/
{{abbr|{{c|diffcruel|{{#ask: [[-Has subobject::{{FULLPAGENAME}}]] [[Has stat id::~*cruel_elemental_damage_resistance_%]]|?Has stat value=|mainlabel=-}} }}
|{{#ask:[[-Has subobject::{{FULLPAGENAME}}]] [[Has stat id::~*cruel_elemental_damage_resistance_%]] |?Has stat text= |mainlabel=-}} }}
/
{{abbr|{{c|diffmerciless|{{#ask: [[-Has subobject::{{FULLPAGENAME}}]] [[Has stat id::~*merciless_elemental_damage_resistance_%]]|?Has stat value=|mainlabel=-}} }}
|{{#ask:[[-Has subobject::{{FULLPAGENAME}}]] [[Has stat id::~*merciless_elemental_damage_resistance_%]] |?Has stat text= |mainlabel=-}} }}


{| class="wikitable mw-collapsible mw-collapsed"
{{cot|Experience Penalty. Last updated: 2016-09-02}}<pre>
! Collapsible Template
|-
|
<pre>
 
Text here
 
</pre>
|}
 
 
{| class="wikitable mw-collapsible mw-collapsed"
! Matlab scripts
|-
|
 
{| class="wikitable mw-collapsible mw-collapsed"
! Experience Penalty. Last updated: 2015-12-10
|-
|
<pre>


%% Experience Penalty
%% Experience Penalty
Line 58: Line 20:
home, clear all, close all
home, clear all, close all
%% Input
%% Input
PlayerLevel    = 1:100;
PlayerLevel    = 1:100; %[30, 10];
MonsterLevel    = 1:85;
MonsterLevel    = 1:90;


%% Calculations
%% Calculations
Line 80: Line 42:


% If the player level is outside the safe zone a multiplier on monsters  
% If the player level is outside the safe zone a multiplier on monsters  
% experience takes effect, reducing the amount by:  
% experience takes effect, reducing the amount. There are two penalties,
XPMultiplier = max(((mPlayerLevel + 5) ./ ...
% one at lower levels and one at higher levels.
    (mPlayerLevel + 5 + EffectiveDifference.^2.5)).^1.5, minEXPMulti);
 
% Low levels:
XPMultiplier_Low = ((mPlayerLevel + 5) ./ (mPlayerLevel + 5 + EffectiveDifference.^2.5)).^1.5;
% High Levels:
LevelThreshold = 95;
BoolHighPenalty = mPlayerLevel >= LevelThreshold;
XPMultiplier_High = (1 - 1 ./ (1 + 0.1 * (mPlayerLevel - 94))) .* BoolHighPenalty;
XPMultiplier_High(isnan(XPMultiplier_High)) = 0;
 
% Total penalty:
XPMultiplier_Tot = max(XPMultiplier_Low .* (1 - XPMultiplier_High), minEXPMulti);


%% Contour plot
%% Contour plot
figure
figure('position', [500, 500, 1100, 600])
[C,h] = contourf(mPlayerLevel,mMonsterLevel,XPMultiplier);
[C,h] = contourf(mPlayerLevel, mMonsterLevel, XPMultiplier_Tot);
ticks = 5;
ticks = 5;
set(gca,'XTick',0:ticks:PlayerLevel(end));
set(gca,'XTick',0:ticks:PlayerLevel(end));
Line 104: Line 76:
PercentualShare = (PlayerLevel + 10).^2.71 ./ sum((PlayerLevel + 10).^2.71,2);
PercentualShare = (PlayerLevel + 10).^2.71 ./ sum((PlayerLevel + 10).^2.71,2);


</pre>
</pre>{{cob}}
|}
{{cot|Chance to hit and avoid attacks. Last updated: 2015-12-10}}<pre>
 
{| class="wikitable mw-collapsible mw-collapsed"
! Chance to hit and avoid attacks. Last updated: 2015-12-10
|-
|
<pre>


%% Chance to hit and avoid attacks.
%% Chance to hit and avoid attacks.
Line 168: Line 134:
ylabel(h,'Chance to hit [%]');
ylabel(h,'Chance to hit [%]');


</pre>
</pre>{{cob}}
|}
{{cot|Armour Reduction. Last updated: 2015-12-10}}<pre>
 
{| class="wikitable mw-collapsible mw-collapsed"
! Armour Reduction. Last updated: 2015-12-10
|-
|
<pre>


%% Armour Reduction  
%% Armour Reduction  
Line 211: Line 171:
ylabel(h,'Raw Physical Damage');
ylabel(h,'Raw Physical Damage');


</pre>
</pre>{{cob}}
|}


{| class="wikitable mw-collapsible mw-collapsed"
{{cot|Plot Energy shield recharge. Last updated: 2015-12-10}}<pre>
! Plot Energy shield recharge. Last updated: 2015-12-10
|-
|
<pre>


%% Plot Energy shield recharge
%% Plot Energy shield recharge
Line 241: Line 196:
grid on
grid on


</pre>
</pre>{{cob}}
|}


{| class="wikitable mw-collapsible mw-collapsed"
{{cot|Leech Mechanics. Last updated: 2017-01-01}}<pre>
! Leech Mechanics. Last updated: 2015-12-10
|-
|
<pre>


%% Leech mechanics for Path of Exile
%% Leech mechanics for Path of Exile
Line 257: Line 207:


%% Input
%% Input
p              = 5000;                % Maximum Life.
hp              = 5000;                % Maximum Life/Mana.
l              = 0.02;                % Increased Leech.
l              = 0.05;                % Damage Leeched as Life/Mana.
m              = 0;                   % Increased Base Leeech Rate.
m              = 2.50;                 % increased Life/Mana Leeched per second.
m_max          = 0;                    % Increased Maximum Leech Rate.
m_max          = 0.15;                % of maximum Life/Mana per second to
q              = 0.02;                % Base Leech Rate.         
                                        % maximum Life/Mana Leech rate.
q_max          = 0.2;                  % Base Maximum Leech Rate.
steps          = 1000;                % Number of steps.


% Damage values from the hit:
% Damage values from the hit:
d              = 4000; %[1000 1000 1000 1000 1000];
damage          = 500000/12;           % Damage dealt.
attacksPerSec  = 5;                   % Attacks per Second:
attacksPerSec  = 12;                   % Attacks per Second.
mobsPerAttack  = 3;                    % Enemies hit by one attack:
mobsPerAttack  = 1;                    % Enemies hit by one attack.
attackTime      = 0:1/attacksPerSec:1;  % The time when the attack started.
numberOfAttacks = 7;                    % Number of attacks done to enemies.
% The time when the attack started:
attackTime      = 0:1/attacksPerSec:(numberOfAttacks - 1)/attacksPerSec;   
% The time when the attack hit the target(s):
% The time when the attack hit the target(s):
hitTime        = kron(attackTime, ones(1,mobsPerAttack)); % [0 0.01 0.02 0.03 0.04];
hitTime        = kron(attackTime, ones(1,mobsPerAttack));
q              = 0.02;                % Base Leech Rate.        
q_max          = 0.20;                % Base Maximum Leech Rate.
steps          = 1000;                 % Number of steps.


%% Calculations
%% Calculations
% Maximum recovery rate:
% Maximum recovery rate:
r_max = (q_max + m_max ) * p;
recovery_rate_max = (q_max + m_max) * hp;


% Leech duration
% Leech duration:
t_dur = d * l / (p *q)   .* ones(1, length(hitTime));
duration_i = floor(damage * l) / (hp *q) .* ones(1, length(hitTime));


% Total allowed leech instance to not exceed the maximum recovery rate
% Total allowed leech instance to not exceed the maximum recovery rate:
n_tot = (q_max + m_max) / (q * (1 + m));
n_tot = (q_max + m_max) / (q * (1 + m));


% Amount of HP leeched:
% Maximum analysis time:
LeechAmount = l .* d;
maxTime = hitTime(end) + duration_i(end);  


% Maximum analysis time:
% Time between each step:
maxTime = hitTime(end) + t_dur(end);      
dt = (maxTime-0)/steps;


% Repeat vectors:
% Repeat vectors:
t = linspace(0, maxTime, steps);
t               = 0:dt:maxTime;
instanceRep = repmat((1:length(hitTime))',1,length(t));
tRep            = repmat(t, length(hitTime), 1);
tRep = repmat(t,length(hitTime),1);
instanceRep     = repmat((1:length(hitTime))', 1, length(t));
AttackTimeRep = repmat(hitTime',1,length(t));
AttackTimeRep   = repmat(hitTime', 1, length(t));
t_durRep = repmat(t_dur',1,length(t));
durationRep    = repmat(duration_i', 1, length(t));


% Boolean conditions to check if there have been an enemy hit and if
% Boolean conditions to check if there have been an enemy hit and if
% the leeched ife is lower than the total amount of life leeched.
% the leeched ife is lower than the total amount of life leeched.
boolHitStart = tRep >= AttackTimeRep;
boolHitStart   = tRep >= AttackTimeRep;
boolLeechEnd = tRep < AttackTimeRep + t_durRep;
boolLeechEnd   = tRep < AttackTimeRep + durationRep;
BoolLeechEndVP = tRep <= AttackTimeRep + dt*0.99;  


% Both of the above conditions must be true for leech to occur:
% Both of the above conditions must be true for leech to occur:
boolLeech = (boolHitStart .* boolLeechEnd);
boolLeech     = (boolHitStart .* boolLeechEnd);
boolLeechVP    = (boolHitStart .* BoolLeechEndVP);


% Base Recovery Rate for each leech instance:
% Base Recovery Rate for each leech instance:
r = (q + m) * p .* boolLeech;
recovery_rate_i = hp * q * (1 + m) .* boolLeech;


% Each active leech instance:
% Each active leech instance:
Line 311: Line 266:


% Base Recovery Rate summarized for all the leech instances:
% Base Recovery Rate summarized for all the leech instances:
r_sum = sum(r);
recovery_rate_sum = sum(recovery_rate_i,1);


% Check that r_sum is not greater than r_max:
% Check that r_sum is not greater than r_max:
boolLimit = r_sum >= r_max;
boolLimit = recovery_rate_sum >= recovery_rate_max;
r_sum = r_max .* boolLimit + r_sum .*(~boolLimit);
recovery_rate_sum = recovery_rate_max .* boolLimit ...
    + recovery_rate_sum .*(~boolLimit);


% Pre-load for for-loop:
% Pre-load for for-loop:
dt = (maxTime-0)/steps;
hp_recovered_i = zeros(length(hitTime), length(t));
HP_i = zeros(length(hitTime),length(t));
hp_recovered_tot = zeros(1, length(t));
HP_tot = zeros(1,length(t));
hp_recovered_totVP = zeros(1, length(t));


for i = 1:length(t)-1;
for i = 1:length(t)-1;
     % HP restored from each leech instance, this is used to check
     % HP restored from each leech instance, this is used to check
     % when each leech instance is finished:
     % when each leech instance is finished:
     HP_i(:,i+1) =  q * p .* boolLeech(:,i) * dt + HP_i(:,i);
     hp_recovered_i(:,i+1) =  q * hp .* boolLeech(:,i) * dt ...
        + hp_recovered_i(:,i);
      
      
     % Total HP restored from all the leech instances:
     % Total HP restored from all the leech instances:
     HP_tot(:,i+1) =  r_sum(:,i) * dt + HP_tot(:,i);
     hp_recovered_tot(:,i+1) =  recovery_rate_sum(:,i) * dt ...
        + hp_recovered_tot(:,i);
   
    % Vaal Pact restores life instanteously:
    hp_recovered_totVP(:,i+1) =  damage * l .* sum(boolLeechVP(:,i),1) ...
        + hp_recovered_totVP(:,i);
end
end


Line 335: Line 297:
leechInstance(leechInstance == 0) = NaN; % Remove zeros from plot.
leechInstance(leechInstance == 0) = NaN; % Remove zeros from plot.
fig(1) = subplot(3,1,1);
fig(1) = subplot(3,1,1);
plot(t, leechInstance(:,:));
colororder = get(gca,'colororder');
plot(t, leechInstance, 'Color', colororder(1,:));
% set(gca, 'YTick', 0:length(hitTime)); % Show integers only.
ylim([0 length(hitTime)+0.5]);
ylim([0 length(hitTime)+0.5]);
xlim([0 maxTime]);
xlim([0 maxTime]);
Line 346: Line 310:
     [rowStart, colStart]  = find(~isnan(leechInstance(i,:)), 1, 'first');
     [rowStart, colStart]  = find(~isnan(leechInstance(i,:)), 1, 'first');
     [rowEnd,  colEnd]    = find(~isnan(leechInstance(i,:)), 1, 'last');
     [rowEnd,  colEnd]    = find(~isnan(leechInstance(i,:)), 1, 'last');
     plot(t(colStart), leechInstance(i, colStart), '.', ...
     plot(t(colStart), leechInstance(i, colStart), 'b.', ...
         t(colEnd),  leechInstance(i, colEnd), 'x');
         t(colEnd),  leechInstance(i, colEnd),'bx', ...
        t(colStart),  leechInstance(i, colStart),'ro');
    % Vaal Pact Start and End:
    plot(t(colStart),  leechInstance(i, colStart),'ro');    
end
end


fig(2) = subplot(3,1,2);
fig(2) = subplot(3,1,2);
[a, h1, h2] = plotyy(t, r_sum, t, r_sum/p);
[ax, h1, h2] = plotyy(t, recovery_rate_sum, t, recovery_rate_sum/hp);
delete(h2);
delete(h2);
NumberOfTicks = 4;
NumberOfTicks = 4;
set(a(1),  'ycolor', 'black', ...          % Change right axis color to black
set(ax(1),  'ycolor', 'black', ...          % Change right axis color to black
             'YTick', 0:r_max/NumberOfTicks:r_max);
             'YTick', 0:recovery_rate_max/NumberOfTicks:recovery_rate_max);
set(a(2),  'ycolor', 'black', ...          % Change left axis color to black
set(ax(2),  'ycolor', 'black', ...          % Change left axis color to black
             'YTick', 0:q_max/NumberOfTicks:q_max);  %
             'YTick', 0:(q_max+m_max)/NumberOfTicks:(q_max+m_max));  %
ylim(a(1), [0 r_max]);
ylim(ax(1), [0 recovery_rate_max]);
ylim(a(2), [0 q_max]);
ylim(ax(2), [0 q_max+m_max]);
xlim([0 maxTime]);
xlim([0 maxTime]);
xlabel('Time, t, [s]');
xlabel('Time, t, [s]');
ylabel(a(1), 'Recovery Rate [HP/s]');  
ylabel(ax(1), 'Recovery rate [HP/s]');  
ylabel(a(2), 'Base Rate [HP/(max hp * s)]');  
ylabel(ax(2), 'Base Rate [HP/(max hp * s)]');  
title('Recovery Rate');
title('Leech Rate');


fig(3) = subplot(3,1,3);
fig(3) = subplot(3,1,3);
plot(t, HP_tot);
plot(t, hp_recovered_tot, 'b', t, hp_recovered_totVP, 'r-.');
ylim([0 inf]);
ylim([0 inf]);
xlim([0 maxTime]);
xlim([0 maxTime]);
xlabel('Time, t, [s]');
xlabel('Time, t, [s]');
ylabel('HP restored, [HP]');
ylabel('HP recovered, [HP]');
title('HP restored from leech');
title('HP recovered from leech');
legend('Recovery rate','Instantenous leech', 'Location','SouthEast')
linkaxes(fig,'x')
linkaxes(fig,'x')


</pre>
</pre>{{cob}}
|}


{| class="wikitable mw-collapsible mw-collapsed"
{{cot|Tab wide buyout creator. Last updated: 2016-03-08}}<pre>
! Tab wide buyout creator. Last updated: 2015-12-13
|-
|
<pre>


%% Tab wide buyout creator
%% Tab wide buyout creator
Line 393: Line 356:
fileName = 'Shop.txt';
fileName = 'Shop.txt';


% Price range:
% Price vector:
priceIncrease = 0.5;
minPrice = 0;    priceIncrease = 0.5; maxPrice = 100;
minPrice = 0;
prices = minPrice:priceIncrease:maxPrice;
maxPrice = 100;


% Define the name of spoiler and its stash name:
% Define the name of spoiler and its stash name:
Line 402: Line 364:
%  Second column: Shorthand stash name.
%  Second column: Shorthand stash name.
currency = {
currency = {
     'mirror',  'mirror';
     'mirror',  'mirror',  prices;
     'exa',      'ex';
     'exa',      'ex',      prices;
     'divine',  'divine';
     'divine',  'divine',  prices;
     'gcp',      'gcp';
     'gcp',      'gcp',      prices;
     'regal',    'regal';
     'regal',    'regal',    prices;
     'regret',  'regret';
     'regret',  'regret',  prices;
     'chaos',    'c';
     'chaos',    'c',        prices;
     'blessed',  'blessed';
     'blessed',  'blessed',  prices;
     'scour',    'scour';
     'scour',    'scour',    prices;
     'alchemy',  'alch';
     'alchemy',  'alch',    prices;
     'fuse',    'fuse';
     'fuse',    'fuse',    prices;
     'chisel',  'chis';
     'chisel',  'chis',    prices;
     'chance',  'chance';
     'chance',  'chance',  prices;
     'jewel',    'jew';
     'jewel',    'jew',      prices;
     'alt',      'alt';
     'alt',      'alt',      prices;
     'chrom',    'chrom';
     'chrom',    'chrom',    prices;
     'vaal',    'vaal';
     'vaal',    'vaal',    prices;
    'coin',    'coin',    0:10:30000;
             };
             };
       
tag = '~b/o';
%% Print Shop
%% Print Shop
% Price vector:
prices = minPrice:priceIncrease:maxPrice;
% Open/create file to write:
% Open/create file to write:
fileID = fopen(fileName,'w');
fileID = fopen(fileName,'w');


% Create buyouts for all the defined currencies in Currency:
% Create buyouts for all the defined currencies in Currency:
for currencyType = 1:length(currency(:,1))
for currencyType = 1:length(currency(:, 1))
     % Create spoiler buyouts for that particular currency type,  
     % Create spoiler buyouts for that particular currency type,  
     % value according to Prices at the following form:
     % value according to Prices at the following form:
     for i = 1:length(prices);
     for i = 1:length(currency{currencyType, 3}(1,:));
         % For Procurement or pre-0.4 Acquisition Plus:
         % For Procurement or pre-0.4 Acquisition Plus:
         % [spoiler="~b/o 2.5 mirror"]
         % [spoiler="~b/o 2.5 mirror"]
Line 443: Line 406:
         % For 0.4+ Acquisition plus:
         % For 0.4+ Acquisition plus:
         % {Stash:1c|include.ignored|wrap|header:~b/o 1 chaos}
         % {Stash:1c|include.ignored|wrap|header:~b/o 1 chaos}
         fprintf(fileID,'{Stash:%g', prices(i)); fprintf(fileID,currency{currencyType,2});  
         fprintf(fileID,'{Stash:%g', currency{currencyType, 3}(1,i)); fprintf(fileID, currency{currencyType,2});  
         fprintf(fileID,'|include.ignored|wrap'); fprintf(fileID,'|header:~b/o %g ', prices(i));  
         fprintf(fileID,'|include.ignored|wrap'); fprintf(fileID, '|header:');
         fprintf(fileID,currency{currencyType,1}); fprintf(fileID,'}');
        fprintf(fileID, tag); fprintf(fileID, ' %g ', currency{currencyType, 3}(1,i));
         fprintf(fileID, currency{currencyType,1}); fprintf(fileID, '}');
%        fprintf(fileID,'\n');
%        fprintf(fileID,'\n');
     end
     end
Line 453: Line 417:
fclose(fileID);
fclose(fileID);


</pre>
 
|}
</pre>{{cob}}
{{cot|Lucky vs. Normal rolls. Last updated: 2016-04-29}}<pre>
 
%% Lucky vs. normal rolls
close all, clear all, home
 
%% Calculations
 
% Chance to crit on the first roll:
A = 0:1/100:1;
 
% Chance to NOT crit on the first roll:
B = 1 - A;
 
% Chance to crit on the second roll:
C = B .* A;
 
% Chance to NOT crit on the second roll:
D = B .* B;
 
% The probability to get a lucky critical strike is the sum of A and C:
LuckyCritChance = min(A + C, 1);
 
%% Plot
figure
plot(100*A,100*A, 100*A,100*LuckyCritChance,'-.');
ylim(100*[0 1])
xlim(100*[0 max(A)])
title('Lucky vs. Normal rolls')
legend('Default chance roll', 'Lucky chance roll', 'Location', 'Southeast')
xlabel('[%]')
ylabel('[%]')
 
</pre>{{cob}}
 
 




---
---
|}
{{cob}}

Latest revision as of 19:09, 15 March 2020

Subpages

Todo list

Scripts

Matlab scripts [Expand]


Experience Penalty. Last updated: 2016-09-02 [Expand]

%% Experience Penalty
% The player also suffers a penalty to XP if the player is too far above 
% or below the monster's level. 
home, clear all, close all
%% Input
PlayerLevel     = 1:100; %[30, 10];
MonsterLevel    = 1:90;

%% Calculations
% Create a repeated matrix:
mPlayerLevel = repmat(PlayerLevel, length(MonsterLevel), 1);
mMonsterLevel = repmat(MonsterLevel, length(PlayerLevel), 1)';

% Minimum amount of experience penalty:
minEXPMulti = 0.01;

% There's a safe zone between player level and monster level where no 
% experience penalty is applied:
SafeZone = floor(3 + mPlayerLevel/16);

% Any additional level difference in excess of this safe range is the
% effective level difference:
EffectiveDifference = max(abs(mPlayerLevel - mMonsterLevel) - SafeZone, 0);
% If the effective difference is negative that implies the player is inside
% the safe zone. Therefore only values =>0 are relevant. 

% If the player level is outside the safe zone a multiplier on monsters 
% experience takes effect, reducing the amount. There are two penalties, 
% one at lower levels and one at higher levels. 

% Low levels:
XPMultiplier_Low = ((mPlayerLevel + 5) ./ (mPlayerLevel + 5 + EffectiveDifference.^2.5)).^1.5;
% High Levels:
LevelThreshold = 95;
BoolHighPenalty = mPlayerLevel >= LevelThreshold;
XPMultiplier_High = (1 - 1 ./ (1 + 0.1 * (mPlayerLevel - 94))) .* BoolHighPenalty;
XPMultiplier_High(isnan(XPMultiplier_High)) = 0;

% Total penalty:
XPMultiplier_Tot = max(XPMultiplier_Low .* (1 - XPMultiplier_High), minEXPMulti);

%% Contour plot
figure('position', [500, 500, 1100, 600])
[C,h] = contourf(mPlayerLevel, mMonsterLevel, XPMultiplier_Tot);
ticks = 5;
set(gca,'XTick',0:ticks:PlayerLevel(end));
set(gca,'YTick',0:ticks:MonsterLevel(end));
h = colorbar;
h.Limits = [0.01 1];
grid minor
shading interp
title('Experience Penalty')
xlabel('Player Level')
ylabel('Monster Level')
% zlabel('Experience efficiency')
ylabel(h,'Experience Efficiency');
%% Party play
% Parties with different character levels will gain different amount of
% experience according to:
PercentualShare = (PlayerLevel + 10).^2.71 ./ sum((PlayerLevel + 10).^2.71,2);

Chance to hit and avoid attacks. Last updated: 2015-12-10 [Expand]

%% Chance to hit and avoid attacks.
close all, clear all, home 
set(0,'DefaultFigureWindowStyle', 'docked');

% Sources:
% http://pathofexile.gamepedia.com/Evasion
% http://pathofexile.gamepedia.com/Accuracy

%% Input
step = 100;
evasionRating = linspace(0, 50000, step);
attackerAccuracy = linspace(0, 4000, step);
chanceToDodge = 0;

%% Calculations
% Create a Mesh grid to be able to do contour plots:
[evasionRatingMesh, attackerAccuracyMesh] = meshgrid(evasionRating, attackerAccuracy);

% Chance to hit is a function if accuracy and evasion rating:
chanceToHit = min(max( attackerAccuracyMesh ./ (attackerAccuracyMesh + (evasionRatingMesh/4).^0.8), 0.05) , 0.95);

% Chance to avoid hits
chanceToAvoidHit = 1 - chanceToHit*(1-chanceToDodge);

%% Contour plot
% Chance to avoid hit contour plot
figure
[C,h] = contourf(evasionRatingMesh,attackerAccuracyMesh,chanceToAvoidHit*100);
clabel(C,h,'labelspacing',200)
% clabel(C,h,'manual')
colormap(cool)
h = colorbar;
h.Limits = [5 95];
grid minor
shading interp
title('Chance to avoid enemy attacks')
xlabel('Defender''s Evasion Rating')
ylabel('Attacker''s Accuracy Rating')
ylabel(h,'Chance to avoid hit [%]');

% Chance to hit contour plot
figure
[C,h] = contourf(attackerAccuracyMesh,evasionRatingMesh, chanceToHit*100);
clabel(C,h,'labelspacing',700)
colormap(cool)
h = colorbar;
h.Limits = [5 95];
grid minor
shading interp
title('Chance to hit enemy')
xlabel('Attacker''s Accuracy Rating')
ylabel('Defender''s Evasion Rating')
% zlabel('Experience efficiency')
ylabel(h,'Chance to hit [%]');

Armour Reduction. Last updated: 2015-12-10 [Expand]

%% Armour Reduction 
close all, clear all, home

% Sources:
% http://pathofexile.gamepedia.com/Armour

%% Input
step = 100;
Armour = linspace(0, 50000, step);
Damage = linspace(0, 10000, step);
%% Calculations
% Create a Mesh grid to be able to do contour plots:
[ArmourMesh, DamageMesh] = meshgrid(Armour, Damage);

Damage_Reduction_FactorMesh = ArmourMesh ./ (ArmourMesh + 10 * DamageMesh);

%% Contour plot
figure
% [C,h] = contourf(ArmourMesh,DamageMesh,Damage_Reduction_FactorMesh*100);
[C,h] = contour(ArmourMesh,Damage_Reduction_FactorMesh*100,DamageMesh, ...
    [100:200:600, 1000:500:2000, 3000:1000:6000, 8000:2000:10000]);
clabel(C,h, 'labelspacing',700);
clabel(C,h,'manual')
colormap(copper)
h = colorbar;
% h.Limits = [0.01 1];
grid minor
shading interp
ylim([0 90])
title('Physical Damage Reduction when Hit')
xlabel('Armour Rating')
ylabel('#% additional Physical Damage Reduction when Hit')
ylabel(h,'Raw Physical Damage');

Plot Energy shield recharge. Last updated: 2015-12-10 [Expand]

%% Plot Energy shield recharge
close all, clear all, home

% Sources:
% http://pathofexile.gamepedia.com/Energy_shield

%% Inputs
r = 0:300;
BaseStart = 2;

%% Calculations
ESStartTime = BaseStart * 100./(100 + r);

%% Plot 
figure
plot(r, ESStartTime)
title('Start of Energy Shield Recharge')
xlabel('#% faster start of Energy Shield Recharge')
ylabel('Start time of Energy Shield Recharge [s]')
grid on

Leech Mechanics. Last updated: 2017-01-01 [Expand]

%% Leech mechanics for Path of Exile
% This script analyses how the leech rate changes with increasing number of
% enemies and number of hits on the enemy. 
close all, clear all, home
set(0,'DefaultFigureWindowStyle', 'docked');

%% Input
hp              = 5000;                 % Maximum Life/Mana.
l               = 0.05;                 % Damage Leeched as Life/Mana.
m               = 2.50;                 % increased Life/Mana Leeched per second.
m_max           = 0.15;                 % of maximum Life/Mana per second to 
                                        % maximum Life/Mana Leech rate.

% Damage values from the hit:
damage          = 500000/12;            % Damage dealt.
attacksPerSec   = 12;                   % Attacks per Second.
mobsPerAttack   = 1;                    % Enemies hit by one attack.
numberOfAttacks = 7;                    % Number of attacks done to enemies.
% The time when the attack started:
attackTime      = 0:1/attacksPerSec:(numberOfAttacks - 1)/attacksPerSec;  
% The time when the attack hit the target(s):
hitTime         = kron(attackTime, ones(1,mobsPerAttack));
q               = 0.02;                 % Base Leech Rate.          
q_max           = 0.20;                 % Base Maximum Leech Rate.
steps           = 1000;                 % Number of steps.

%% Calculations
% Maximum recovery rate:
recovery_rate_max = (q_max + m_max) * hp;

% Leech duration:
duration_i = floor(damage * l) / (hp *q) .* ones(1, length(hitTime));

% Total allowed leech instance to not exceed the maximum recovery rate:
n_tot = (q_max + m_max) / (q * (1 + m));

% Maximum analysis time:
maxTime = hitTime(end) + duration_i(end);    

% Time between each step:
dt = (maxTime-0)/steps;

% Repeat vectors:
t               = 0:dt:maxTime;
tRep            = repmat(t, length(hitTime), 1);
instanceRep     = repmat((1:length(hitTime))', 1, length(t));
AttackTimeRep   = repmat(hitTime', 1, length(t));
durationRep     = repmat(duration_i', 1, length(t));

% Boolean conditions to check if there have been an enemy hit and if
% the leeched ife is lower than the total amount of life leeched.
boolHitStart   = tRep >= AttackTimeRep;
boolLeechEnd   = tRep < AttackTimeRep + durationRep;
BoolLeechEndVP = tRep <= AttackTimeRep + dt*0.99; 

% Both of the above conditions must be true for leech to occur:
boolLeech      = (boolHitStart .* boolLeechEnd);
boolLeechVP    = (boolHitStart .* BoolLeechEndVP);

% Base Recovery Rate for each leech instance:
recovery_rate_i = hp * q * (1 + m) .* boolLeech;

% Each active leech instance:
leechInstance =  instanceRep .* boolLeech;

% Base Recovery Rate summarized for all the leech instances:
recovery_rate_sum = sum(recovery_rate_i,1);

% Check that r_sum is not greater than r_max:
boolLimit = recovery_rate_sum >= recovery_rate_max;
recovery_rate_sum = recovery_rate_max .* boolLimit ...
    + recovery_rate_sum .*(~boolLimit);

% Pre-load for for-loop:
hp_recovered_i = zeros(length(hitTime), length(t));
hp_recovered_tot = zeros(1, length(t));
hp_recovered_totVP = zeros(1, length(t));

for i = 1:length(t)-1;
    % HP restored from each leech instance, this is used to check
    % when each leech instance is finished:
    hp_recovered_i(:,i+1) =  q * hp .* boolLeech(:,i) * dt ... 
        + hp_recovered_i(:,i);
    
    % Total HP restored from all the leech instances:
    hp_recovered_tot(:,i+1) =  recovery_rate_sum(:,i) * dt ...
        + hp_recovered_tot(:,i);
    
    % Vaal Pact restores life instanteously:
    hp_recovered_totVP(:,i+1) =  damage * l .* sum(boolLeechVP(:,i),1) ...
        + hp_recovered_totVP(:,i);
end

%% Plot 
figure
leechInstance(leechInstance == 0) = NaN; % Remove zeros from plot.
fig(1) = subplot(3,1,1);
colororder = get(gca,'colororder');
plot(t, leechInstance, 'Color', colororder(1,:));
% set(gca, 'YTick', 0:length(hitTime)); % Show integers only.
ylim([0 length(hitTime)+0.5]);
xlim([0 maxTime]);
xlabel('Time, t, [s]');
ylabel('Leech instance');
title('Leech instance');
for i = 1:length(hitTime);
    hold on
    % Find the start and end point of each instance and mark it:
    [rowStart, colStart]   = find(~isnan(leechInstance(i,:)), 1, 'first');
    [rowEnd,   colEnd]     = find(~isnan(leechInstance(i,:)), 1, 'last');
    plot(t(colStart), leechInstance(i, colStart), 'b.', ...
         t(colEnd),   leechInstance(i, colEnd),'bx', ...
         t(colStart),   leechInstance(i, colStart),'ro');
     % Vaal Pact Start and End:
    plot(t(colStart),   leechInstance(i, colStart),'ro');     
end

fig(2) = subplot(3,1,2);
[ax, h1, h2] = plotyy(t, recovery_rate_sum, t, recovery_rate_sum/hp);
delete(h2);
NumberOfTicks = 4;
set(ax(1),   'ycolor', 'black', ...          % Change right axis color to black
            'YTick', 0:recovery_rate_max/NumberOfTicks:recovery_rate_max);
set(ax(2),   'ycolor', 'black', ...          % Change left axis color to black
            'YTick', 0:(q_max+m_max)/NumberOfTicks:(q_max+m_max));  %
ylim(ax(1), [0 recovery_rate_max]);
ylim(ax(2), [0 q_max+m_max]);
xlim([0 maxTime]);
xlabel('Time, t, [s]');
ylabel(ax(1), 'Recovery rate [HP/s]'); 
ylabel(ax(2), 'Base Rate [HP/(max hp * s)]'); 
title('Leech Rate');

fig(3) = subplot(3,1,3);
plot(t, hp_recovered_tot, 'b', t, hp_recovered_totVP, 'r-.');
ylim([0 inf]);
xlim([0 maxTime]);
xlabel('Time, t, [s]');
ylabel('HP recovered, [HP]');
title('HP recovered from leech');
legend('Recovery rate','Instantenous leech', 'Location','SouthEast')
linkaxes(fig,'x')

Tab wide buyout creator. Last updated: 2016-03-08 [Expand]

%% Tab wide buyout creator
home; close all; clear all; 
% This script will create spoiler tab buyouts for use in shop
% templates, for example in Procurement or Acquisition Plus. 

%% Input
% File name to save the template to:
fileName = 'Shop.txt';

% Price vector:
minPrice = 0;    priceIncrease = 0.5;  maxPrice = 100;
prices = minPrice:priceIncrease:maxPrice;

% Define the name of spoiler and its stash name:
%   First column: Name of spoiler tag, can be Currency format, ilvl... 
%   Second column: Shorthand stash name.
currency = {
    'mirror',   'mirror',   prices;
    'exa',      'ex',       prices;
    'divine',   'divine',   prices;
    'gcp',      'gcp',      prices;
    'regal',    'regal',    prices;
    'regret',   'regret',   prices;
    'chaos',    'c',        prices;
    'blessed',  'blessed',  prices;
    'scour',    'scour',    prices;
    'alchemy',  'alch',     prices;
    'fuse',     'fuse',     prices;
    'chisel',   'chis',     prices;
    'chance',   'chance',   prices;
    'jewel',    'jew',      prices;
    'alt',      'alt',      prices;
    'chrom',    'chrom',    prices;
    'vaal',     'vaal',     prices;
    'coin',     'coin',     0:10:30000;
            };
        
tag = '~b/o';

%% Print Shop
% Open/create file to write:
fileID = fopen(fileName,'w');

% Create buyouts for all the defined currencies in Currency:
for currencyType = 1:length(currency(:, 1))
    % Create spoiler buyouts for that particular currency type, 
    % value according to Prices at the following form:
    for i = 1:length(currency{currencyType, 3}(1,:));
        % For Procurement or pre-0.4 Acquisition Plus:
        % [spoiler="~b/o 2.5 mirror"]
        % {Stash:2.5mirror|include.ignored}
        % [/spoiler]
%         fprintf(fileID,'[spoiler="~b/o %g ', prices(i)); fprintf(fileID,currency{type,1}); fprintf(fileID,'"]');
%         fprintf(fileID,'\n{Stash:%g', prices(i)); fprintf(fileID,currency{type,2}); fprintf(fileID,'|include.ignored}');
%         fprintf(fileID,'\n[/spoiler]');
%         fprintf(fileID,'\n');
        
        % For 0.4+ Acquisition plus:
        % {Stash:1c|include.ignored|wrap|header:~b/o 1 chaos}
        fprintf(fileID,'{Stash:%g', currency{currencyType, 3}(1,i)); fprintf(fileID, currency{currencyType,2}); 
        fprintf(fileID,'|include.ignored|wrap'); fprintf(fileID, '|header:'); 
        fprintf(fileID, tag); fprintf(fileID, ' %g ', currency{currencyType, 3}(1,i));
        fprintf(fileID, currency{currencyType,1}); fprintf(fileID, '}');
%         fprintf(fileID,'\n');
    end
end

% Close the written file:
fclose(fileID);


Lucky vs. Normal rolls. Last updated: 2016-04-29 [Expand]

%% Lucky vs. normal rolls
close all, clear all, home

%% Calculations

% Chance to crit on the first roll:
A = 0:1/100:1;

% Chance to NOT crit on the first roll:
B = 1 - A;

% Chance to crit on the second roll:
C = B .* A;

% Chance to NOT crit on the second roll:
D = B .* B;

% The probability to get a lucky critical strike is the sum of A and C:
LuckyCritChance = min(A + C, 1);

%% Plot
figure
plot(100*A,100*A, 100*A,100*LuckyCritChance,'-.');
ylim(100*[0 1])
xlim(100*[0 max(A)])
title('Lucky vs. Normal rolls')
legend('Default chance roll', 'Lucky chance roll', 'Location', 'Southeast')
xlabel('[%]')
ylabel('[%]')



---