I've made an NPC in Tmodloder, a little girl known as the florist, and I have the mod HERO's MOD installed, it shows up in the npc spawn list, yet not as a town NPC, and also won't spawn when clicked, unlike all other NPCs and entities in the game
These are my Files:
Florist.ini
[Stats]
frameCount=26
animationType=0
aiStyle=7
height=40
width=20
damage=0
defense=2
lifeMax=250
scale=1
soundHit=1
soundKilled=1
type=-1
knockBackResist=.1
townNPC=True
friendly=True
Florist.cs
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Audio;
using Terraria.DataStructures;
using Terraria.GameContent.Creative;
using Terraria.ID;
using Terraria.ModLoader;
namespace ElanTown.NPCs
{
public class Florist : ModNPC
{
public static bool TownSpawn() {
return true;
}
public static string SetName() {
if(Main.rand.Next(2)==0){
return "Sophie";
}
else
{
return "Amy";
}
}
public static string Chat() {
int result = Main.rand.Next(3);
string text = "";
if (result == 0)
{
text = "I Asked {Name of Guide} for a bow, this isn't what I expected.";
}
else if (result == 1)
{
text = "Hey there! Would You Like to Buy some Flowers?";
}
else if (result == 2)
{
text = "Would You like to buy some seeds?";
}
return text;
}
public static void SetupShop(Chest chest) {
int index=0;
chest.item[index].SetDefaults(309);
index++;
chest.item[index].SetDefaults(307);
index++;
chest.item[index].SetDefaults(310);
index++;
chest.item[index].SetDefaults(312);
index++;
chest.item[index].SetDefaults(308);
index++;
chest.item[index].SetDefaults(2357);
index++;
chest.item[index].SetDefaults(311);
index++;
}
}
}
Florist.png
Florist Head.png
If anyone was wondering, the chest.item[index].SetDefaults({int}); in Florist.cs was the internal item IDs of all the herb seeds
Related
I am making a program which you can create and load in a flashcard pack using csv files. When a csv file is chosen it opens other UI with the question, answer and image for a flashcard and will keep on looping until all the flashcards in the pack are gone through using a foreach loop.
However the foreach loop would keep on looping without the user pressing the next button. To fix this I did:
while (Continue() == false) { } //this is at the end of the foreach loop
}
}
private bool Continue()
{
if (btn_NextFlashcard_WasClicked) return true;
Application.DoEvents();
Thread.Sleep(250);
Application.DoEvents();
return false;
}
private bool btn_NextFlashcard_WasClicked;
private void btn_NextFlashcard_Click(object sender, EventArgs e)
{
btn_NextFlashcard_WasClicked = true;
}
This fixed the problem of it looping again without the button for the next flashcard being pressed but now it doesn't even open the second UI for me to press the next flashcard button.
How would I fix this? Any help would be greatly appreciated.
Code for foreach loop:
public void ReadFlashcardPack(string file)
{
var records = engine.ReadFile(file);
foreach (var record in records)
{
Console.WriteLine("New foreach loop");
lblQuestion.Text = record.question;
lblAnswer.Text = record.answer;
lblAnswer.Visible = false;
btn_NextFlashcard_WasClicked = false;
//check if there is an image
if (record.image == "FALSE")
{
Image.Hide();
}
else
{
Image.Show();
Image.Image = Properties.Resources.test_image;
}
while (Continue() == false) { }
}
}
The records also come from a class: [DelimitedRecord(",")]
public class FlashcardPack
{
public string question;
public string answer;
public string image;
}
And then a new instance of FileHelpers engine is made private FileHelperEngine<FlashcardPack> engine = new FileHelperEngine<FlashcardPack>(); to read the csv file and every time the foreach loop loops record.question, record.answer and record.image changes depending on what line the loop is on.
One idea that comes to mind is to store the list of records outside of the method, keep track of the next record that should be read, and modify the method to just read the next record.
Then, in your click event, you can just call the method again until all records have been read.
private string filePath = #"f:\private\temp\temp.csv"; // Use your file path here
private List<FlashcardPack> records;
private int nextRecord;
public void ReadNextRecord()
{
if (records == null)
{
records = engine.ReadFile(filePath).ToList();
nextRecord = 0;
}
else if (nextRecord >= records.Count)
{
// Do something when all records have been read
nextRecord = 0;
}
// Get next record and increment our variable
var record = records[nextRecord++];
lblQuestion.Text = record.question;
lblAnswer.Text = record.answer;
lblAnswer.Visible = false;
btn_NextFlashcard_WasClicked = false;
//check if there is an image
if (record.image == "FALSE")
{
Image.Hide();
}
else
{
Image.Show();
Image.Image = Properties.Resources.test_image;
}
}
private void btn_NextFlashcard_Click(object sender, EventArgs e)
{
ReadNextRecord();
}
Here's a working sample that uses the concept above which might help you get your code working, since I can't see your whole project:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<Flashcard> flashcards;
private int nextRecord;
// Use a valid path on your system here (the file doesn't need to exist)
private const string FilePath = #"f:\public\temp\temp.csv";
private void LoadFlashcards()
{
flashcards = Engine.ReadFile(FilePath);
nextRecord = 0;
}
public void DisplayNextFlashcard()
{
if (flashcards == null)
{
LoadFlashcards();
}
else if (nextRecord >= flashcards.Count)
{
// Do something when all records have been read
nextRecord = 0;
}
var flashcard = flashcards[nextRecord++];
lblQuestion.Text = flashcard.Question;
lblAnswer.Visible = false;
lblAnswer.Text = flashcard.Answer;
Image.Visible = flashcard.Image;
Image.Image = Properties.Resources.FlashcardImage;
}
private void btn_NextFlashcard_Click(object sender, EventArgs e)
{
DisplayNextFlashcard();
}
}
class Flashcard
{
public string Question { get; set; }
public string Answer { get; set; }
public bool Image { get; set; }
public static Flashcard Parse(string csvLine)
{
if (csvLine == null) throw new ArgumentNullException(nameof(csvLine));
var parts = csvLine.Split(',').Select(item => item.Trim()).ToList();
if (parts.Count != 3) throw new FormatException(
"csvLine does not contain 3 comma-separated items.");
return new Flashcard
{
Question = parts[0],
Answer = parts[1],
Image = !parts[2].Equals("FALSE", StringComparison.OrdinalIgnoreCase)
};
}
}
class Engine
{
public static List<Flashcard> ReadFile(string filePath)
{
if (filePath == null) throw new ArgumentNullException(nameof(filePath));
if (!File.Exists(filePath)) CreateFile(filePath);
return File.ReadAllLines(filePath).Select(Flashcard.Parse).ToList();
}
private static void CreateFile(string filePath)
{
File.CreateText(filePath).Close();
File.WriteAllText(filePath,
"What is more useful when it is broken?, An egg, TRUE\n" +
"What belongs to you but other people use it more?, Your name, FALSE\n" +
"I have three eyes all in a row. When the red one opens " +
"no one can go. What am I?, A traffic light, TRUE");
}
}
I'm a beginner to coding. A friend of mine used to help me but now he's busy so I have to do things alone. The game has a function that remember the name the player input before playing the game as well as the score of the player. Right now, my problem is that when I play a game, it doesn't show up in my leaderboard scene. And then when I play another round with a different name, I can see the previous score but not my current one. It's like the data is delayed to appear.
void ReplaceRank(string player, int currentScore) {
string oldName;
int oldScoreNumber;
for (int i = 0; i < 10; i++) {
if (currentScore > scores[i]) {
highscoreShow.enabled = true;
oldScoreNumber = scores[i];
oldName = PlayerPrefs.GetString(oldPlayerName[i]);
PlayerPrefs.SetInt(oldScore[i], currentScore);
PlayerPrefs.SetString(oldPlayerName[i], player);
Debug.Log(currentScore);
if (i <= 9) {
ReplaceRank(oldName, oldScoreNumber);
}
break;
}
}
}
private void GetAllKeys() {
oldScore = new List<string>();
oldPlayerName = new List<string>();
scores = new List<int>();
for (int i = 11; i < 21; i++) {
if (PlayerPrefs.GetString("score" + i + "Name", "") == "") {
PlayerPrefs.SetString("score" + i + "Name", "");
}
oldPlayerName.Add("score" + i + "Name");
oldScore.Add("score" + i);
scores.Add(PlayerPrefs.GetInt("score" + i, 0));
}
}
Even though this seems trivial its not , saving is kinda tricky, they are a few things you can do to make it easier e.g you should save the scores as a list
Saving
add scores to list
convert list of scores to Json
save json string in player prefs
Loading
get json string from player prefs
convert Json to list
updated list in script
wrote this class quickly.. its tested and works but you might have to modify it to suit your needs and improve it
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace ScoreBoard
{
[Serializable]
public class PlayerScore
{
public string Name;
public int Score;
public PlayerScore(string name, int score)
{
Name = name;
Score = score;
}
}
[Serializable]
// we need to store list of scores in a container class so we can change it to json
public class PlayerScoresRankedListContainer
{
public List<PlayerScore> PlayerScoresRanked = new List<PlayerScore>();
}
[Serializable]
public class ScoresRanked : MonoBehaviour
{
public static PlayerScoresRankedListContainer PlayerScoresListContainer =new PlayerScoresRankedListContainer();
public void Awake()
{
//example of usage
//get saved items
if (PlayerPrefs.GetString("PlayerScoresRanked").Length > 0)
{
PlayerScoresListContainer.PlayerScoresRanked = GetSortedListFromPlayerPrefs();
DebugShowScores();
}
else
{
//test the class asving items
AddScoreToRankedList("player1", 1000);
AddScoreToRankedList("player2", 20);
AddScoreToRankedList("player3", 100);
SaveListAsJSONInPlayerPrefs();
}
}
private void AddScoreToRankedList(string player, int currentScore)
{
var score = new PlayerScore(player, currentScore);
if (DoesScoreAlreadyExist(score))
{
//we remove a score if it already exists so we can updated it
//you might not need this maybe you just want to keep adding scores
PlayerScoresListContainer.PlayerScoresRanked.RemoveAll(x => x.Name == score.Name);
PlayerScoresListContainer.PlayerScoresRanked.Add(score);
}
else
{
PlayerScoresListContainer.PlayerScoresRanked.Add(score);
}
}
public void SaveListAsJSONInPlayerPrefs()
{
var jsonlist = JsonUtility.ToJson(PlayerScoresListContainer);
Debug.Log("LOG ITEMS BEING SAVED: "+jsonlist);
PlayerPrefs.SetString("PlayerScoresRanked", jsonlist);
}
public List<PlayerScore> GetSortedListFromPlayerPrefs()
{
var jsonlist = PlayerPrefs.GetString("PlayerScoresRanked");
var ListContainer = JsonUtility.FromJson<PlayerScoresRankedListContainer>(jsonlist);
var listsorted = ListContainer.PlayerScoresRanked.OrderByDescending(x => x.Score).ToList();
return listsorted;
}
public bool DoesScoreAlreadyExist(PlayerScore scoreToChcek)
{
if (PlayerScoresListContainer.PlayerScoresRanked.Exists(x => x.Name == scoreToChcek.Name))
{
return true;
}
else
{
return false;
}
}
public void DebugShowScores()
{
foreach (var playerScore in PlayerScoresListContainer.PlayerScoresRanked)
{
Debug.Log(playerScore.Name + " " + playerScore.Score);
}
}
}
}
I'm implementing linked lists. I'm trying to code different kinds of functionalities I can which may be of use to me. The reason I'm not using the inbuilt List<>() is because of my requirement of my lab work to implement linked lists our selves which we are going to use for any further functionality.
My current functionalities include printing a single node, printing all nodes, adding a node at the end, replacing a node and one I'm currently working on is deleting/removing a node. (Credits to youtuber Jeff Chastine I mostly used what he did in his tutorial)
I was hoping to have other people look at what I'm doing in delete node (in LinkedList.cs) because I feel as though using Exception handling may not be the right path.
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkedListImplementation
{
class Program
{
static void Main(string[] args)
{
LinkedList myList = new LinkedList();
myList.append(3);
myList.append(14);
myList.append(14);
myList.append(34);
myList.append(89);
myList.append(556);
myList.print();
myList.deleteNode(1);
myList.print();
//myList.replaceData(5, 80);
Console.ReadLine();
}
}
}
Node.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkedListImplementation
{
class Node
{
public int data;
public Node nextNode;
public Node(int data)
{
this.data = data;
nextNode = null;
}
public void singleDisplay(int data)
{
if(nextNode != null)
{
if (this.data == data)
{
Console.WriteLine("My data {0}", data);
}
nextNode.singleDisplay(data);
}
if (nextNode == null)
{
if(this.data != data)
{
Console.WriteLine("Value not found");
}
else
{
Console.WriteLine("My data {0}", data);
}
}
}
public void completeDisplay()
{
if(nextNode != null)
{
Console.Write(data + " -> ");
nextNode.completeDisplay();
}
else
{
Console.WriteLine(data);
}
}
public void addNodeAtEnd(int data)
{
if(nextNode == null)
{
nextNode = new Node(data);
}
else
{
nextNode.addNodeAtEnd(data);
}
}
public void replaceNodeData(int data, int repData)
{
if(this.data == data)
{
this.data = repData;
}
else
{
if(nextNode == null)
{
Console.WriteLine("Value Not Found");
}
else
{
nextNode.replaceNodeData(data, repData);
}
}
}
}
}
LinkedList.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkedListImplementation
{
class LinkedList
{
public Node head;
public LinkedList()
{
head = null;
}
public void append(int data)
{
if (head == null)
{
head = new Node(data);
}
else
{
head.addNodeAtEnd(data);
}
}
public void print()
{
if (head != null)
{
head.completeDisplay();
}
else
{
Console.WriteLine("List Not Found");
}
}
public void singlePrint(int data)
{
if(head != null)
{
head.singleDisplay(data);
}
else
{
Console.WriteLine("List Not Found");
}
}
public void replaceData(int data, int repData)
{
if(head != null)
{
head.replaceNodeData(data, repData);
}
else
{
Console.WriteLine("List Not Found");
}
}
public void deleteNode(int data)
{
Node current = head;
Node temp = new Node(0);
if(current == null)
{
Console.WriteLine("List does not exist");
}
else
{
while (current.data != data)
{
temp = current;
current = current.nextNode;
try
{
if (current.data != data && current == null)
{}
}
catch(Exception)
{
//Console.WriteLine(ex.Message);
break;
}
}
try
{
if (current.data == data && current.nextNode == null)
{
current = temp;
current.nextNode = null;
}
else if (current.data == data && current.nextNode != null)
{
current = current.nextNode;
temp.nextNode = current;
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
Why are you using multiple try catch blocks in the deleteNode method, which should be DeleteNode by the way? A single try catch block will give you cleaner code, and catch any exceptions that happen in it. You could always add specialized exception types if you were looking for better error handling. See the multiple catch block example here
try
{
if (current == null)
{
Console.WriteLine("List does not exist");
}
else
{
while (current.data != data)
{
temp = current;
current = current.nextNode;
if (current.data != data && current == null)
{
}
}
if (current.data == data && current.nextNode == null)
{
current = temp;
current.nextNode = null;
}
else if (current.data == data && current.nextNode != null)
{
current = current.nextNode;
temp.nextNode = current;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Could you help me here, this is my friend's work(actually don't know where did he get this code, it uses vb language) and i'm trying to convert the code to c#. Thought it was easy, even though i lack of c# knowledge, and i'm stacked from here. I found a vb.net to c# converter from the net, and this is the result:
*see the comment below
clsProcess.cs:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
[Serializable()]
public class clsProcess : IComparable<clsProcess>
{
public int Priority
{
get { return _Priority; }
set { _Priority = value; }
}
public Color ProcessColor
{
get { return _ProcessColor; }
set { _ProcessColor = value; }
}
public double ArrTime
{
get { return _ArrTime; }
set { _ArrTime = value; }
}
public double ExeTime
{
get { return _ExeTime; }
set { _ExeTime = value; }
}
public string Label
{
get { return _Label; }
set { _Label = value; }
}
public clsProcess()
{
}
public clsProcess(int prior, double arr, double exe, string lbl, Color clr)
{
_Priority = prior;
_ArrTime = arr;
_ExeTime = exe;
_Label = lbl;
_ProcessColor = clr;
}
private double _ArrTime;
private double _ExeTime;
private string _Label;
private int _Priority;
private Color _ProcessColor;
public int CompareTo(clsProcess other)
{
switch ((modGlobals.SortColumn))
{
//The method SortType from modGlobals.cs is the error.
//Error says: The name 'SortType' does not exist in the current context
//I'm getting error from here:
case SortType.Arr:
return this.ArrTime.CompareTo(other.ArrTime);
case SortType.Exe:
return this.ExeTime.CompareTo(other.ExeTime);
case SortType.Label:
return this.Label.CompareTo(other.Label);
case SortType.Prior:
return this.Priority.CompareTo(other.Priority);
//Until here.
}
}
}
modGlobals.cs:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
static class modGlobals
{
public enum SortType //The error referring to.
{
Arr,
Exe,
Prior,
Label
}
public static SortType SortColumn; //I doubt it has something to do here.
public static List<clsProcess> CreateMemberwiseClone(List<clsProcess> pList)
{
List<clsProcess> tempList = new List<clsProcess>();
int i = 0;
for (i = 0; i <= pList.Count - 1; i++) {
tempList.Add(CloneProcess(pList[i]));
}
return tempList;
}
public static clsProcess CloneProcess(clsProcess process)
{
clsProcess temp = new clsProcess();
temp.ExeTime = process.ExeTime;
temp.ArrTime = process.ArrTime;
temp.Label = process.Label;
temp.Priority = process.Priority;
temp.ProcessColor = process.ProcessColor;
return temp;
}
public static void MergeBlocks(ref List<clsBlock> blocks)
{
if (blocks.Count < 2)
return;
int i = 0;
while (i < blocks.Count - 1) {
if (blocks[i].BlockCaption == blocks[i + 1].BlockCaption) {
blocks[i].BlockLength += blocks[i + 1].BlockLength;
blocks.RemoveAt(i + 1);
i -= 1;
}
i += 1;
}
}
}
Could you give me an alternate solution for here?
try
public int CompareTo(clsProcess other)
{
switch ((modGlobals.SortColumn))
{
case modGlobals.SortType.Arr:
return this.ArrTime.CompareTo(other.ArrTime);
case modGlobals.SortType.Exe:
return this.ExeTime.CompareTo(other.ExeTime);
case modGlobals.SortType.Label:
return this.Label.CompareTo(other.Label);
case modGlobals.SortType.Prior:
return this.Priority.CompareTo(other.Priority);
}
//This next part will happen if the switch statement doesnt find a match
//use this to return some default value or a value that tells you it didnt find something
//I'll use 0 as an example
return 0;
//now all paths return a value, even if it doesnt find a match in the switch statement
}
Your static class modGlobals should only have static members.
The SortType should be static.
public static enum SortType
{
Arr,
Exe,
Prior,
Label
}
I am picking up C# and as a beginners exercise I tried to code a simple Tekken Tournament roster. The problem is, that I cannot find a way how to apply a method of class Fighter onto the whole list of fighters, as there are no names of the variable, or at least I think that is the problem.
using System;
using System.Collections.Generic;
namespace TekkenConsoleTournament
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Enter nicknames of players, finished by 0: \n");
int numFighter=0;
String nickname;
List <Fighter> allFighters = new List<Fighter>();
while ((nickname = Console.ReadLine()) != "") {
allFighters.Add(new Fighter(nickname));
numFighter ++;
}
Console.WriteLine(allFighters.ForEach(Fighter.getName()));
Console.WriteLine(foreach(Fighter in allFighters) {getName();});
//for (int counter = 0; counter <= fighter; counter++) {
// Fighter[counter.getName();
//}
}
}
}
And the Fighter.cs
using System;
namespace TekkenConsoleTournament
{
public class Fighter
{
private int matches, won, lost, draw;
String name;
public Fighter (String name)
{
this.matches = this.won = this.lost = 0;
this.name = name;
}
public void wonMatch()
{
matches++;won++;
}
public void lostMatch()
{
matches++;lost++;
}
public void drawMatch()
{
matches++;draw++;
}
public int[] getStats()
{
int[] stats = {this.matches,this.won,this.lost,this.draw};
return stats;
}
public String getName()
{
return this.name;
}
}
}
At first, I d like to print the names of all fighters, then maybe the stats and then as an exercise try making the code remember who fought who and put them in two dimensional matrix based on the result of the fight.
Use a foreach loop ?
foreach(var fighter in allFighters)
{
// do something with fighter
var name = fighter.getName();
Console.WriteLine(name);
}
I assume there is a getName method, if there is not use your field or property name to get current fighter's name.
Your mistake is you are putting ForEach loops inside of Console.WriteLine method.You should do the opposite.And this syntax is wrong:
foreach(Fighter in allFighters)
It should be like this:
foreach(Fighter fighter in allFighters)
Or you can use var as shown in the above code.
You're close, but not quite. Try these options:
Console.WriteLine(string.Join(", ", allFighters.Select(f => f.getName())));
allFighters.ForEach(fighter => Console.Writeline(fighter.getName()));
foreach (Fighter f in allFighters)
{
Console.WriteLine(f.getName());
}