hey all, and thank you for even clicking this message, this is a BIG ask as i need someone to help me with what seems to be like never documented or unforgotten information.
First off lets talk what im using,
Html 5 , CSS 3, Javascript
& Node.js & Express (with nodemon, jquery, body-parser and mysql as my db) as a bakend
Im working on my childhood life project, Ive recenlty turned 30 and started to really learn how to code, so in my mind a adoptables site was the best place to begin once i got the grasp of things. (BAD IDEA!) but i feel like ive came way to far to quit now.
I've played games like magistream, Dragoncave, tales of ostlea, and even tried to create my own games in 2010-2015 thru mysidia adoptables script (if you are familiar) however all of these sites like the features I would like (magistream's server always has hiccups and DC never really felt like a community to me), and as my mother always used to say “if you want something done right…” lol.
Ive gotten pretty far with (as a beginner with javascript) the features include.
Adopting adoptables from different areas based on rarity (works)
Training adoptables (works)
Leveling system (works) (btw i think this is my favorite, just cause the way it works)
dynamically made viewpage based on adopt (like if you click on one you will go to their page with the required stats)
Quest System -( hard as hell, but its doable, just because of the pure /get requests for every page)
Currency system (gold & rubies) (works for every memeber (admin, test & test2)
I need help with 2 major things i feel like truly make an adoptables game and 1 feature that correlates with my training script (Battles)
Marketplace (works)
I have a sample breeding script i keep testing over and over but i always get {cant find parent 1 message}
i would like it to work like i get parent 1's ID (Parent1 is whoever the female is) and (Parent2 is whoever the male parent is)
and thats where i run into my problems, i have the column “id” in my database as well as “username” that ties that adoptable to the user.
any help with a battleing script would be helpful as well. I will include my training GET and POST requests as well.
Training Script
app.get('/training', function (request, response) {
if (request.session.loggedin && request.session.username) {
const username = request.session.username;
// Retrieve the user's adopted adoptables
const sqlUserAdoptables = `SELECT id, name, type, rarity, image, image2, image3, gender, level, hp, str, def, spd, xp, mother, father, lineage, battleswon, battleslost, description, breed, username, growth_stage, next_growth
FROM owned_adopts
WHERE username = ?;`;
connection.query(sqlUserAdoptables, [username], (err, results) => {
if (err) {
console.error('Error retrieving user adoptables:', err);
response.status(500).json({ message: 'Internal Server Error' });
return;
}
const adoptables = results; // Assign the fetched data to the adoptables variable
const adoptableId = "";
response.render('training', {
pageTitle: 'Antillia - Training',
username: username,
adoptables: adoptables,
styles: ['main.css', 'profile.css', 'train.css'],
adoptableId: adoptableId
});
});
} else {
response.redirect('/');
}
});
app.post('/train', function (request, response) {
if (request.session.loggedin && request.session.username) {
const username = request.session.username;
const { str, def, spd, adoptableId } = request.body;
if (!adoptableId) {
return response.status(400).send('Invalid adoptable ID.');
}
const selectSql = 'SELECT * FROM owned_adopts WHERE id = ?';
connection.query(selectSql, [adoptableId], (err, results) => {
if (err) {
console.error('Error retrieving adoptable:', err);
return response.status(500).send('Error retrieving adoptable.');
}
const adoptable = results[0];
if (adoptable.growth_stage === 0) {
return response.status(400).send("Cannot train an Egg.");
}
// Calculate XP gained with level-based boost
const xpGained = Math.floor(Math.random() * 17.8) * 14;
const xpBoost = Math.floor(xpGained * (adoptable.level * 0.234));
const totalXpGained = xpGained + xpBoost;
// Calculate new attribute values with level-based boost
const strBoost = Math.floor(adoptable.level * 1.8);
const newStr = adoptable.str + Math.floor(Math.random() * 15) + (str ? 4 : 23) + strBoost;
const newDef = adoptable.def + Math.floor(Math.random() * 15) + (def ? 3 : 27) + strBoost;
const newSpd = adoptable.spd + Math.floor(Math.random() * 15) + (spd ? 6 : 29) + strBoost;
const selectUserSql = 'SELECT * FROM users WHERE username = ?';
connection.query(selectUserSql, [username], (err, userResults) => {
if (err) {
console.error('Error retrieving user:', err);
return response.status(500).send('Error retrieving user.');
}
if (userResults.length === 0) {
console.error('User not found.');
return response.status(404).send('User not found.');
}
const user = userResults[0];
const userGold = parseInt(user.gold); // Parse user's gold as an integer
const strCost = adoptable.level * 6;
const defCost = adoptable.level * 4;
const spdCost = adoptable.level * 5;
const updateSql = 'UPDATE owned_adopts SET str = ?, def = ?, spd = ?, xp = xp + ? WHERE id = ?';
connection.query(updateSql, [newStr, newDef, newSpd, xpGained, adoptableId], (err, results) => {
if (err) {
console.error('Error updating adoptable:', err);
return response.status(500).send('Error updating adoptable.');
}
if (userGold < strCost || userGold < defCost || userGold < spdCost) {
return response.status(400).send('Insufficient gold.');
}
const updatedGold = userGold - strCost - defCost - spdCost;
const updateUserSql = 'UPDATE users SET gold = ? WHERE username = ?';
connection.query(updateUserSql, [updatedGold, username], (err, updateUserResult) => {
if (err) {
console.error('Error updating user:', err);
return response.status(500).send('Error updating user.');
}
const xpToNextLevel = adoptable.xp_to_next_level;
const currentXP = adoptable.xp + xpGained;
let levelUp = false;
if (currentXP >= xpToNextLevel) {
levelUp = true;
const newLevel = adoptable.level + 1;
const newXpToNextLevel = Math.floor(xpToNextLevel * 1.2);
const newHP = adoptable.hp + (newLevel * 120);
const levelUpSql = 'UPDATE owned_adopts SET level = ?, xp = 0, xp_to_next_level = ?, hp = ? WHERE id = ?';
connection.query(levelUpSql, [newLevel, newXpToNextLevel, newHP, adoptableId], (err, results) => {
if (err) {
console.error('Error updating adoptable:', err);
return response.status(500).send('Error updating adoptable.');
}
});
}
const updatedSelectSql = 'SELECT * FROM owned_adopts WHERE id = ?';
connection.query(updatedSelectSql, [adoptableId], (err, updatedResults) => {
if (err) {
console.error('Error retrieving updated adoptable:', err);
return response.status(500).send('Error retrieving updated adoptable.');
}
const updatedAdoptable = updatedResults[0];
// Create an object to store the stats gained in green color
const statsGained = {
str: newStr - adoptable.str,
def: newDef - adoptable.def,
spd: newSpd - adoptable.spd
};
// Pass the updated values and gold cost as URL parameters
const redirectUrl = `/viewadopt/${adoptableId}?str=${newStr}&def=${newDef}&spd=${newSpd}&goldCost=${strCost + defCost + spdCost}`;
response.redirect(redirectUrl);
});
});
});
});
});
}
});
Breeding Script
//BREEDING LOGIC!
const rarityCost = {
common: 100,
uncommon: 200,
rare: 400,
"ultra-rare": 600,
legendary: 750
// Add more rarities and their corresponding costs as needed
};
// Calculate breeding cost based on rarity and level
const calculateBreedingCost = (rarity, level) => {
const baseCost = rarityCost[rarity] || 0;
const levelMultiplier = Math.max(1, Math.sqrt(level));
const breedingCost = baseCost * levelMultiplier;
return Math.floor(breedingCost);
};
function canBreed(parent1, parent2) {
// Check if parents have the required breed combinations for hybrid adoptables
if (
(parent1.breed === "manticore" && parent2.breed === "direwolf" && parent1.hybridbreed1 === "manticore" && parent2.hybridbreed2 === "direwolf") ||
(parent1.breed === "manticore" && parent2.breed === "Ibex" && parent1.hybridbreed1 === "manticore" && parent2.hybridbreed2 === "Ibex")
// Add more breed combinations here as needed
) {
return true;
}
// Check if the parents have reached the required growth stage
if (parent1.growth_stage < 2 || parent2.growth_stage < 2) {
return false;
}
// Check if the parents have compatible genders
if ((parent1.gender === 'male' && parent2.gender === 'male') || (parent1.gender === 'female' && parent2.gender === 'female')) {
return false;
}
// Random chance for refusal
const refusalChance = 0.22; // 22% chance of refusal
const shouldRefuse = Math.random() < refusalChance;
if (shouldRefuse) {
return false;
}
// Add more breeding eligibility conditions as needed
// All conditions passed, parents are eligible for breeding
return true;
}
const currentPlayer = req.session.username; // Assuming you have stored the username in the session
// Create the child adoptable
function hasEnoughCurrency(user, requiredCurrency) {
return user.gold >= requiredCurrency;
}
function deductCurrency(user, amount) {
user.gold -= amount;
// Assuming the deduction logic is properly implemented elsewhere and user.gold is updated accordingly
return user.gold;
}
function generateChildName() {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const nameLength = 5; // Adjust the desired length of the name
let name = '';
for (let i = 0; i < nameLength; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
const randomChar = characters.charAt(randomIndex);
name += randomChar;
}
return name;
}
// Breeding function
function breed(parent1, parent2, userCurrency) {
// Check if the parents are eligible for breeding
if (!canBreed(parent1, parent2)) {
return { success: false, message: 'Parents are not eligible for breeding.' };
}
// Check if the parents meet the requirements for creating a hybrid child
if (
(parent1.breed === "manticore" && parent2.breed === "direwolf" && parent1.hybridbreed1 === "manticore" && parent2.hybridbreed2 === "direwolf") ||
(parent1.breed === "manticore" && parent2.breed === "Ibex" && parent1.hybridbreed1 === "manticore" && parent2.hybridbreed2 === "Ibex")
// Add more breed combinations here as needed
) {
// Generate a hybrid child
const child = generateHybridChild(parent1, parent2);
// Return the result
return { success: true, message: 'Hybrid breeding successful.', child: child };
}
// Generate a regular child
const child = generateRegularChild(parent1, parent2);
// Get the rarity of the parents
const rarity1 = parent1.rarity;
const rarity2 = parent2.rarity;
// Calculate the breeding cost based on the rarity of the parents
const cost1 = calculateBreedingCost(rarity1, parent1.level);
const cost2 = calculateBreedingCost(rarity2, parent2.level);
// Check if the user has enough currency to cover the breeding cost
if (!hasEnoughCurrency(userCurrency, cost1 + cost2)) {
return { success: false, message: 'Insufficient currency to cover the breeding cost.' };
}
// Deduct the breeding cost from the user's currency
const remainingCurrency = deductCurrency(userCurrency, cost1 + cost2);
// Assign correct IDs based on gender
if (parent1.gender === 'male') {
child.father = parent1.id;
child.mother = parent2.id;
} else {
child.mother = parent1.id;
child.father = parent2.id;
}
// Function to generate a regular child adoptable
function generateRegularChild(parent1, parent2) {
// Select the parent to use for specific values
const selectedParent = Math.random() < 0.5 ? parent1 : parent2;
const child = {
name: generateChildName(parent1, parent2),
type: selectedParent.type,
rarity: selectedParent.rarity,
image: selectedParent.image,
imagealt: selectedParent.imagealt,
imagealt2: selectedParent.imagealt2,
imagealt3: selectedParent.imagealt3,
gender: getRandomGender(),
level: 0,
hp: 110,
str: Math.floor(0.35 * (parent1.str + parent2.str)),
def: Math.floor(0.35 * (parent1.def + parent2.def)),
spd: Math.floor(0.35 * (parent1.spd + parent2.spd)),
xp: 0,
mother: parent1.gender,
father: parent2.gender,
battleswon: 0,
battleslost: 0,
egg_description: selectedParent.egg_description,
hatchling_description: selectedParent.hatchling_description,
adult_description: selectedParent.adult_description,
description: selectedParent.description,
breed: selectedParent.breed,
username: currentPlayer,
growth_stage: 0,
next_growth: selectedParent.next_growth
};
return child;
}
function generateHybridChild(parent1, parent2) {
let resultingBreed;
// Check the breed combinations and assign the resulting breed
if (
(parent1.breed === "manticore" && parent2.breed === "direwolf") ||
(parent1.breed === "direwolf" && parent2.breed === "manticore")
) {
resultingBreed = "direcore";
} else if (
(parent1.breed === "manticore" && parent2.breed === "Ibex") ||
(parent1.breed === "Ibex" && parent2.breed === "manticore")
) {
resultingBreed = "chimera";
}
// Add more breed combinations and their resulting breeds here as needed
// Use parent1 breed as fallback breed if no specific combination is met
if (!resultingBreed) {
resultingBreed = parent1.breed;
}
// Generate the child adoptable
const child = {
name: generateChildName(parent1, parent2),
type: parent1.type,
rarity: parent1.rarity,
image: parent1.image,
imagealt: parent1.imagealt || parent2.imagealt,
imagealt2: parent1.imagealt2 || parent2.imagealt2,
imagealt3: parent1.imagealt3 || parent2.imagealt3,
gender: getRandomGender(),
level: 0,
hp: parent1.hp,
str: Math.floor(0.35 * (parent1.str + parent2.str)),
def: Math.floor(0.35 * (parent1.def + parent2.def)),
spd: Math.floor(0.35 * (parent1.spd + parent2.spd)),
xp: 0,
mother: parent1.gender,
father: parent2.gender,
battleswon: 0,
battleslost: 0,
egg_description: parent1.egg_description,
hatchling_description: parent1.hatchling_description,
adult_description: parent1.adult_description,
description: parent1.description,
breed: resultingBreed,
username: currentPlayer,
growth_stage: 0,
next_growth: parent1.next_growth
};
return child;
}
// Return success message, remaining currency, and the child adoptable
return { success: true, message: 'Breeding successful!', remainingCurrency, child };
}
function getRandomGender() {
// Assuming there are two genders: male and female
const genders = ["male", "female"];
const randomIndex = Math.floor(Math.random() * genders.length);
return genders[randomIndex];
}
// POST /breed
app.post('/breed', function(request, response) {
if (request.session.loggedin && request.session.username){
const username = request.session.username;
const { parent1Id, parent2Id } = request.body;
console.log('Parent1 ID:', parent1Id);
console.log('Parent2 ID:', parent2Id);
// Step 1: Retrieve the information of parent1 from the database
const sqlParent1 = 'SELECT * FROM owned_adopts WHERE id = ?';
connection.query(sqlParent1, [parent1Id], (err, parent1Results) => {
if (err) {
console.error('Error retrieving parent1 information:', err);
return res.status(500).json({ message: 'Internal Server Error' });
}
// Check if parent1 exists
if (parent1Results.length === 0) {
return res.status(404).json({ message: 'Parent1 not found' });
}
const parent1 = parent1Results[0];
// Step 2: Retrieve the information of parent2 from the database
const sqlParent2 = 'SELECT * FROM owned_adopts WHERE id = 4';
connection.query(sqlParent2, [parent2Id], (err, parent2Results) => {
if (err) {
console.error('Error retrieving parent2 information:', err);
return res.status(500).json({ message: 'Internal Server Error' });
}
// Check if parent2 exists
if (parent2Results.length === 0) {
return res.status(404).json({ message: 'Parent2 not found' });
}
const parent2 = parent2Results[0];
// Step 3: Check if parents are eligible for breeding
if (!canBreed(parent1, parent2)) {
return res.status(400).json({ message: 'Parents are not eligible for breeding' });
}
// Step 4: Generate offspring data
const userCurrency = {}; // Replace with your user currency retrieval logic
const username = req.session.username; // Assuming you have stored the username in the session
const offspring = breed(parent1, parent2, userCurrency, username);
// Rest of the code...
// Step 5: Insert the offspring into the database
const sqlInsert = `INSERT INTO owned_adopts (name, type, rarity, image, imagealt, imagealt2, imagealt3, gender, level, hp, str, def, spd, xp, mother, father, battleswon, battleslost, egg_description, hatchling_description, adult_description, description, breed, username, growth_stage, next_growth)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
connection.query(sqlInsertOffspring, offspring.child, (err, result) => {
if (err) {
console.error('Error inserting offspring:', err);
return res.status(500).json({ message: 'Internal Server Error' });
}
const offspringId = result.insertId;
// Step 6: Update parents' breeding information
const sqlUpdateParents = 'UPDATE owned_adopts SET last_bred = CURRENT_TIMESTAMP() WHERE id IN (?, ?)';
connection.query(sqlUpdateParents, [parent1Id, parent2Id], (err) => {
if (err) {
console.error('Error updating parents breeding information:', err);
return res.status(500).json({ message: 'Internal Server Error' });
}
console.log('Breeding successful!');
return res.json({ message: 'Breeding successful', offspringId });
});
});
});
});
});