Path of Exile Wiki

Please consider helping keep the wiki up to date. Check the to-do list of updates needed for version 3.14.0.

Game data exports will becoming later as the technical changes in addition to regular changes take some more time.

READ MORE

Path of Exile Wiki
Advertisement

This user "Illviljan" prefers to use the enhanced profile.

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('[%]')



---

Advertisement