Adoptables site in 2023, like magistream and dragoncave,

Started by
4 comments, last by hplus0603 10 months ago

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 });
        });
      });
    });
  });
});


Advertisement

It's unclear to me what you're asking for.

You're saying you have a bug in that some function doesn't work.

I suggest you add some console logging before and after the line that prints the message that it doesn't work, to verify what the data are that you expect to be getting.

enum Bool { True, False, FileNotFound };

hey, thanks for replying, ill try to be more clear and percise.
|
the issue im having is with the sql query.
my owned_adopts table has an ID but when i try to get the ID's if parent1 and parent2 adoptable the server cant seem to find it.

and with the battle script, ive included the training script for reference, just any tips or ways to work it to a battle system that singles out 2 of the adoptable ID's and simulates a battle that has the values played with eachother
ie. “spd” goes first

damage does str- def

something like that.
im so sorry if i dont make sense, ive been rattling my brain for days over this.
ive even lined the code up side by side just to get the same function of the sql (like the way i get the ID's for training i tried to grab he ids for breeding the same way)

I'd expect to see an error message coming from the SQL query like “Error number 1048; Column ‘id’ cannot be null” that would give guidance on where to look.

Do you have an exact error message that goes with it? I don't expect that's what you're seeing: “Error number 0123: the server can't seem to find it

The error codes and exact messages are essential in tracking down bugs like this.

@Phoeniix also, all your code is way too much to read in a forum.

If you have a particular query you want help with, then all you need to post is:

  1. the important columns of the table (the columns actually used in the query, and any primary key)
  2. the query text you're actually running
  3. an example of the result you're getting (including error messages, or if it returns no rows without error, say that)

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement