Experience Penalty. Last updated: 2015-12-10
|
%% 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;
MonsterLevel = 1:85;
%% 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 by:
XPMultiplier = max(((mPlayerLevel + 5) ./ ...
(mPlayerLevel + 5 + EffectiveDifference.^2.5)).^1.5, minEXPMulti);
%% Contour plot
figure
[C,h] = contourf(mPlayerLevel,mMonsterLevel,XPMultiplier);
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
|
%% 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
|
%% 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
|
%% 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: 2016-02-03
|
%% 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
p = 5000; % Maximum Life.
l = 0.01; % Increased Leech.
m = 0.00; % Increased Base Leeech Rate.
m_max = 0.00; % Increased Maximum Leech Rate.
% Damage values from the hit:
d = 1000;
attacksPerSec = 4; % Attacks per Second.
mobsPerAttack = 5; % Enemies hit by one attack.
numberOfAttacks = 5; % 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.2; % Base Maximum Leech Rate.
steps = 1000; % Number of steps.
%% Calculations
% Maximum recovery rate:
r_max = (q_max + m_max) * p;
% Leech duration
t_dur = floor(d * l) / (p *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) + t_dur(end);
% Repeat vectors:
t = linspace(0, maxTime, steps);
instanceRep = repmat((1:length(hitTime))',1,length(t));
tRep = repmat(t,length(hitTime),1);
AttackTimeRep = repmat(hitTime',1,length(t));
t_durRep = repmat(t_dur',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 + t_durRep;
BoolLeechEndVP = tRep <= AttackTimeRep + (maxTime-0)/steps;
% 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:
r = p * q * (1 + m) .* boolLeech;
% Each active leech instance:
leechInstance = instanceRep .* boolLeech;
% Base Recovery Rate summarized for all the leech instances:
r_sum = sum(r,1);
% Check that r_sum is not greater than r_max:
boolLimit = r_sum >= r_max;
r_sum = r_max .* boolLimit + r_sum .*(~boolLimit);
% Pre-load for for-loop:
dt = (maxTime-0)/steps;
HP_i = zeros(length(hitTime),length(t));
HP_tot = zeros(1,length(t));
HP_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_i(:,i+1) = q * p .* boolLeech(:,i) * dt + HP_i(:,i);
% Total HP restored from all the leech instances:
HP_tot(:,i+1) = r_sum(:,i) * dt + HP_tot(:,i);
% Vaal Pact restores life instanteously:
HP_totVP(:,i+1) = d * l .* sum(boolLeechVP(:,i),1) + HP_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, r_sum, t, r_sum/p);
delete(h2);
NumberOfTicks = 4;
set(ax(1), 'ycolor', 'black', ... % Change right axis color to black
'YTick', 0:r_max/NumberOfTicks:r_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 r_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_tot, 'b', t, HP_totVP, 'r-.');
ylim([0 inf]);
xlim([0 maxTime]);
xlabel('Time, t, [s]');
ylabel('HP restored, [HP]');
title('HP restored from leech');
legend('Recovery rate','Instantenous leech', 'Location','SouthEast')
linkaxes(fig,'x')
|
Tab wide buyout creator. Last updated: 2016-03-08
|
%% 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
|
%% 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('[%]')
|
---
|