#include <LiquidCrystal.h>
#include <Keypad.h>
#include <math.h>
#define LCD_RS 12
#define LCD_E 11
#define LCD_D4 10
#define LCD_D5 9
#define LCD_D6 8
#define LCD_D7 7
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
byte rowPins[KEYPAD_ROWS] = {5, 4, 3, 2};
byte colPins[KEYPAD_COLS] = {A3, A2, A1, A0};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
long mainStat; // 주스탯
float mainStatPercent; // 주스탯 %
long mainStatNoPercent; // % 미적용 주스탯
long subStat; // 부스탯
float subStatPercent; // 부스탯 %
long subStatNoPercent; // %미적용 부스탯
long attackPower; // 공마
float attackPowerPercent; // 공마 %
float damagePercent; // 뎀 %
float bossDamagePercent; // 보공뎀 %
float finalDamagePercent; // 최종뎀 %
float criticalDamagePercent; // 크뎀 %
long oldEquipMainStat; // 기존 장비의 주스탯 증가량
long oldEquipSubStat; // 기존 장비의 부스탯 증가량
long oldEquipAllStat; // 기존 장비의 올스탯 증가량
long oldEquipAttackPower; // 기존 장비의 공격력 증가량
long newEquipMainStat; // 새로운 장비의 주스탯 증가량
long newEquipSubStat; // 새로운 장비의 부스탯 증가량
long newEquipAllStat; // 새로운 장비의 올스탯 증가량
long newEquipAttackPower; // 새로운 장비의 공격력 증가량
bool isStatsInputDone = false; // A 모드의 완료 판정
bool isOldEquipInputDone = false; // 1번 모드의 완료 판정
bool isNewEquipInputDone = false; // 2번 모드의 완료 판정
long power; // 현재 or 새로운 전투력
long oldpower; // 바뀌기 전 전투력
void setup() {
lcd.begin(16, 2);
lcd.print("MapleStory");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("Power Calculator");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
void loop() {
char key = keypad.getKey();
if (key == '1') {
if (isStatsInputDone) {
inputOldEquipment();
isOldEquipInputDone = true;
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Run A first");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
} else if (key == '2') {
if (isStatsInputDone && isOldEquipInputDone) {
inputNewEquipment();
isNewEquipInputDone = true;
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Run 1 first");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
} else if (key == '3') {
if (isStatsInputDone && isOldEquipInputDone && isNewEquipInputDone) {
updateStatsWithNewEquipment();
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Run 2 first");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
} else if (key == 'A') {
inputStats();
isStatsInputDone = true;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Done!");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
} else if (key == 'B') {
if (isStatsInputDone) {
displayStats();
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Run A first");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
} else if (key == 'C') {
if (isStatsInputDone) {
displayPower();
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Run A first");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
}
}
void inputOldEquipment() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Old Main Stat:");
lcd.setCursor(0, 1);
oldEquipMainStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Old Sub Stat:");
lcd.setCursor(0, 1);
oldEquipSubStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Old All % Stat:");
lcd.setCursor(0, 1);
oldEquipAllStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Old Atk Pwr:");
lcd.setCursor(0, 1);
oldEquipAttackPower = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Old Equip Done!");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
void inputNewEquipment() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("New Main Stat:");
lcd.setCursor(0, 1);
newEquipMainStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("New Sub Stat:");
lcd.setCursor(0, 1);
newEquipSubStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("New All % Stat:");
lcd.setCursor(0, 1);
newEquipAllStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("New Atk Pwr:");
lcd.setCursor(0, 1);
newEquipAttackPower = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("New Equip Done!");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
void updateStatsWithNewEquipment() {
mainStat = mainStat - (oldEquipMainStat - newEquipMainStat);
subStat = subStat - (oldEquipSubStat - newEquipSubStat);
mainStatPercent = mainStatPercent - (oldEquipAllStat - newEquipAllStat);
subStatPercent = subStatPercent - (oldEquipAllStat - newEquipAllStat);
attackPower = attackPower - (oldEquipAttackPower - newEquipAttackPower);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Stats Updating...");
for (int i = 0; i < 14; i++) {
lcd.setCursor(0, 1);
lcd.print("[");
for (int j = 0; j <= i; j++) {
lcd.print("=");
}
for (int j = i + 1; j < 14; j++) {
lcd.print(".");
}
lcd.print("]");
delay(214);
}
oldpower = power;
long adjustedMainStat = mainStat * (1 + mainStatPercent) + mainStatNoPercent;
long adjustedSubStat = subStat * (1 + subStatPercent) + subStatNoPercent;
float totalDamagePercent = 1 + damagePercent + bossDamagePercent;
power = floor((adjustedMainStat * 4 + adjustedSubStat) * 0.01 * floor(attackPower * (1 + attackPowerPercent)) * totalDamagePercent * (1 + finalDamagePercent) * (1.35 + criticalDamagePercent));
long powerdiff = power - oldpower;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("power difference");
lcd.setCursor(0, 1);
lcd.print(powerdiff);
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
}
void inputStats() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Main Stat :");
lcd.setCursor(0, 1);
mainStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Main Stat % :");
lcd.setCursor(0, 1);
mainStatPercent = inputFloat() * 0.01;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Non-% Main :");
lcd.setCursor(0, 1);
mainStatNoPercent = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sub Stat :");
lcd.setCursor(0, 1);
subStat = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sub Stat % :");
lcd.setCursor(0, 1);
subStatPercent = inputFloat() * 0.01;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Non-% Sub :");
lcd.setCursor(0, 1);
subStatNoPercent = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Atk Power :");
lcd.setCursor(0, 1);
attackPower = inputNumber();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Atk % :");
lcd.setCursor(0, 1);
attackPowerPercent = inputFloat() * 0.01;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Damage % :");
lcd.setCursor(0, 1);
damagePercent = inputFloat() * 0.01;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Boss Dmg % :");
lcd.setCursor(0, 1);
bossDamagePercent = inputFloat() * 0.01;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Final Dmg % :");
lcd.setCursor(0, 1);
finalDamagePercent = inputFloat() * 0.01;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Crit Dmg % :");
lcd.setCursor(0, 1);
criticalDamagePercent = inputFloat() * 0.01;
}
long inputNumber() {
String input = "";
char key;
while (true) {
key = keypad.getKey();
if (key >= '0' && key <= '9') {
lcd.setCursor(input.length(), 1);
lcd.print(key);
input += key;
}
if (key == 'D') {
input = "";
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
}
if (key == '#') {
break;
}
}
return input.toInt();
}
float inputFloat() {
String input = "";
char key;
while (true) {
key = keypad.getKey();
if ((key >= '0' && key <= '9') || key == '*') {
lcd.setCursor(input.length(), 1);
lcd.print(key == '*' ? '.' : key);
input += (key == '*' ? '.' : key);
}
if (key == 'D') {
input = "";
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
}
if (key == '#') {
break;
}
}
return input.toFloat();
}
void displayStats() {
int currentDisplay = 0;
while (true) {
lcd.clear();
lcd.setCursor(0, 0);
switch (currentDisplay) {
case 0:
lcd.print("Main Stat :");
lcd.setCursor(0, 1);
lcd.print(mainStat);
break;
case 1:
lcd.print("Main Stat % :");
lcd.setCursor(0, 1);
lcd.print(mainStatPercent);
break;
case 2:
lcd.print("Non-% Main :");
lcd.setCursor(0, 1);
lcd.print(mainStatNoPercent);
break;
case 3:
lcd.print("Sub Stat :");
lcd.setCursor(0, 1);
lcd.print(subStat);
break;
case 4:
lcd.print("Sub Stat % :");
lcd.setCursor(0, 1);
lcd.print(subStatPercent);
break;
case 5:
lcd.print("Non-% Sub :");
lcd.setCursor(0, 1);
lcd.print(subStatNoPercent);
break;
case 6:
lcd.print("Atk Power :");
lcd.setCursor(0, 1);
lcd.print(attackPower);
break;
case 7:
lcd.print("Atk % :");
lcd.setCursor(0, 1);
lcd.print(attackPowerPercent);
break;
case 8:
lcd.print("Damage % :");
lcd.setCursor(0, 1);
lcd.print(damagePercent);
break;
case 9:
lcd.print("Boss Dmg % :");
lcd.setCursor(0, 1);
lcd.print(bossDamagePercent);
break;
case 10:
lcd.print("Final Dmg % :");
lcd.setCursor(0, 1);
lcd.print(finalDamagePercent);
break;
case 11:
lcd.print("Crit Dmg % :");
lcd.setCursor(0, 1);
lcd.print(criticalDamagePercent);
break;
default:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
return;
}
while (true) {
char key = keypad.getKey();
if (key == '#') {
currentDisplay++;
break;
}
}
}
}
void displayPower() {
long adjustedMainStat = mainStat * (1 + mainStatPercent) + mainStatNoPercent;
long adjustedSubStat = subStat * (1 + subStatPercent) + subStatNoPercent;
float totalDamagePercent = 1 + damagePercent + bossDamagePercent;
power = floor((adjustedMainStat * 4 + adjustedSubStat) * 0.01 * floor(attackPower * (1 + attackPowerPercent)) * totalDamagePercent * (1 + finalDamagePercent) * (1.35 + criticalDamagePercent));
while (true) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Power");
lcd.setCursor(0, 1);
lcd.print(power);
while (true) {
char key = keypad.getKey();
if (key == '#') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Mode :");
return;
}
}
}
}