Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
i'm a beginner at C++ and i tried to make a script for a Trinity Core World of Warcraft private server but it seems that some of the codes ran successfully and the others are escaped for unknown reason..
here's the code
#include "ScriptPCH.h"
#include "DisableMgr.h"
class LearnSpellsOnLevelUp : public PlayerScript
{
public:
LearnSpellsOnLevelUp()
: PlayerScript("LearnSpellsOnLevelUp"){};
void OnLevelChanged(Player* player, uint8 oldLevel)
{
if (player->getClass() == 3 && player->getLevel() >= 12) // ran
{
if (player->HasSpell(23356)) // ran
return; // ran
else // ran
player->LearnSpell(23356, false); // ran
player->GetSession()->SendAreaTriggerMessage("|cff00FF00You Learnt new Spell [Taming Lesson]!|r"); // ran
}
if (player->getClass() == 9) // Warlock // ran
{
if (player->getLevel() >= 2) // ran
{
if (player->HasSpell(44163)) // ran
return;
else
player->LearnSpell(44163, false); // ran
player->GetSession()->SendAreaTriggerMessage("|cff00FF00You Learnt new Spell [Summon Imp]!|r"); // ran
}
else if (player->getLevel() >= 10)
{
if (player->HasSpell(25112))
return;
else
player->LearnSpell(25112, false);
player->GetSession()->SendAreaTriggerMessage("|cff00FF00You Learnt new Spell [Summon Voidwalker]!|r");
}
else if (player->getLevel() >= 20)
{
if (player->HasSpell(712))
return;
else
player->LearnSpell(712, false);
player->GetSession()->SendAreaTriggerMessage("|cff00FF00You Learnt new Spell [Summon Succubus]!|r");
}
else if (player->getLevel() >= 30)
{
if (player->HasSpell(691))
return;
else
player->LearnSpell(691, false);
player->GetSession()->SendAreaTriggerMessage("|cff00FF00You Learnt new Spell [Summon Felhunter]!|r");
}
else
return;
}
}
};
void AddSC_LearnSpellsOnLevelUp()
{
new LearnSpellsOnLevelUp();
}
i wrote next to the codes that ran successfully // ran
Pay close attention to the order of your getLevel conditions.
if (player->getLevel() >= 2)
{
}
// Here, it's certain that the level is < 2, since it wasn't >= 2.
// Thus, none of these following tests will be true.
else if (player->getLevel() >= 10)
{
}
else if (player->getLevel() >= 20)
{
}
else if (player->getLevel() >= 30)
{
}
else
return;
You should test the levels starting with the greatest one and work your way donwnward.
if (player->getLevel() >= 30)
{
}
// The level is less than 30. Is it greater than 20?
else if (player->getLevel() >= 20)
{
}
// The level is less than 20. Is it greater than 10?
else if (player->getLevel() >= 10)
{
}
// The level is less than 10. Is it greater than 2?
else if (player->getLevel() >= 2)
{
}
else
return;
Looks like there is simply a logic bug. Let's look at this statement:
if (player->getLevel() >= 2) // ran - ok so far
And now a lot of this:
else if (player->getLevel() >= 10) - and others (comparing with 20, 30)
Now suppose your 'player' has 15 level - looks like the intent was to run the second if block (e.g. where you compare with >= 10)
But there is a problem: if the level is 15 then everytime only the first if-block is executed (because obviously 15 >= 2).
Solution: compare to range, like this:
if ((player->getLevel() >= 2) && (player->getLevel() < 10))
...
else if ((player->getLevel() >= 10) && (player->getLevel() < 20))
...
And so on.
Related
I got some issue with useState and "if else" statement. I wanted to change displayed text with a click.
When I checking if counter icrement is working, it works, but when I add setText in "if else" statement there is a problem and just doesnt work properly. Icnrement strats to work strange when clicking and change a text is just imposible. Even in console increment looks wrong. Can someone help what I am doing wrong?
let counter = 0;
const [txt, setTxt] = useState("Text1");
const handleClick = (e) => {
if (
e.target.classList.contains("fa-angle-right") || e.target.classList.contains("fa-angle-left")
) {e.target.classList.contains("fa-angle-right") ? counter++ : counter--;
if (counter === 1) {
console.log(counter);
setTxt("Text2");
} else if (counter === 2) {
console.log(counter);
setTxt("Txt3")
} else if (counter > 2) {
counter = 0;
console.log(counter);
setTxt("Text1");
} else if (counter < 0) {
counter = 2;
console.log(counter);
setTxt("Text3");
} else if (counter === 0) {
console.log(counter);
setTxt("Txt1");
}
}
};
Every time setTxt('...') is executed, the component is re-rendered and the function executes again, so counter gets the value of 0.
If you want to preserve the value of your counter between renders, put it as a new state ( const [counter, setCounter] = useState(0) )
OK, #AdriánFernándezMartínez I did that way and its close. Just after first clik, in a first "if" (if (counter === 1)) console shows 0 and i have to click twice to chage it and change Txt (but is should be 1 after setCounter(counter + 1)). Next, in a third "if" (else if (counter > 2)) console shows 3 and again I need to click twice to change Txt (after 1st click its 0 and after 2nd it become 1). Still need help.
const [counter, setCounter] = useState(0);
const [txt, setTxt] = useState("Text1");
const handleClick = (e) => {
if (
e.target.classList.contains("fa-angle-right") ||
e.target.classList.contains("fa-angle-left")
) {
e.target.classList.contains("fa-angle-right")
? setCounter(counter + 1)
: setCounter(counter + 1);
console.log(counter);
if (counter === 1) {
console.log(counter);
setTxt("Text2");
} else if (counter === 2) {
console.log(counter);
setTxt("Text3");
} else if (counter > 2) {
setCounter(0);
console.log(counter);
setTxt("Text1");
} else if (counter < 0) {
setCounter(2);
console.log(counter);
setTxt("Text3");
} else if (counter === 0) {
console.log(counter);
setTxt("Text1");
}
}
};
if (value >= 2) {
return 1
} else if (value >= 1) {
return 0.9;
} else if (value >= 0.8) {
return 0.7
} else if (value >= 0.5) {
return 0.5;
} else {
return 0;
}
How to solve this if-else ladder. If i use switch cyclometric complexity increases and also also values feels like true.
In some cases the solution is breakaway code. Not everyone likes it - I do like it.
It just means you handle situations "from the top" and end situations with a return
pseudocode in any language...
(Everything should be in a function anyway...)
HandleTemperature(float t)
{
if (t > 90)
{
RunEmergencyCooling();
return;
}
if (round.t == 63)
{
DealWithgMagicValue();
return;
}
if (round.t > 40)
{
Debug.("normal temps! no worries!);
return;
}
// if you get to here, temp is very lopw
RunEmergencyHeating();
}
(In many languages there's a "finally" or "always do" concept, which can work well w/. breakaway dcode.)
Your example ...
Step 1, put in in a function as it should be anyway, Step 2 use "breakaway chunks".
float HandleValue(float v)
{
if (2.0 <= v) {
return 1
}
if (0.7 < v && v < 2.0) {
return 0.9;
}
if (0.13 <= v && v <= 0.7) {
return 17.6;
}
log didn't find a bracket in HandleValue
return default value
}
Every bracket is totally explicit. You can easily build testing code from there, too.
Those annoying long blocks before errors ...
Breakaway is particularly clean-looking in error cases...
Something()
{
if comms.text != 17.2
{
.. 100s of lines of code here ..
.. they are all indented ..
}
else
{
an error!
}
}
Some (but not all) believe this is better:
Something()
{
if comms.text == 17.2
{
an error!
return; .. note the "return" in breakaway code
}
.. 100s of lines of code here ..
.. no need for indentation ..
}
"Breakaway code" may work for you in some cases; in any event you can be aware of the approach.
I just created a countdown method in Java, but i have a problem when the countdowner broadcasts the messages: 60(and down) seconds until the game starts!
The broadcast gets sent *4. Does anyone know any solution to this?
Here is my code:
Main plugin;
public StartCountdown(Main pl) {
plugin = pl;
}
public static int timeUntilStart;
#Override
public void run() {
for(Player p1 : Bukkit.getOnlinePlayers()){
if(timeUntilStart == 0) {
if(!Game.canStart()) {
plugin.restartCountdown();
ChatUtilities.broadcast(ChatColor.RED + "Not enough players to start. Countdown will");
ChatUtilities.broadcast(ChatColor.RED + "restart.");
p1.playSound(p1.getLocation(), Sound.ENDERDRAGON_WINGS, 5, 1);
return;
}
Game.start();
}
for(Player p : Bukkit.getOnlinePlayers()){
p.setLevel(timeUntilStart);
if(timeUntilStart < 11 || timeUntilStart == 60 || timeUntilStart == 30) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 0);
if(timeUntilStart == 1) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 1);
}
ChatUtilities.broadcast(String.valueOf(timeUntilStart)
+ " §6Seconds until the game starts!");
}
}
}
timeUntilStart -= 1;
}
}
You are broadcasting for every player that is online. You need to move any code that you don't want to run for every player outside of the for loop.
#Override
public void run() {
if (timeUntilStart == 0) {
if (!Game.canStart()) {
plugin.restartCountdown();
ChatUtilities.broadcast(ChatColor.RED + "Not enough players to start. Countdown will");
ChatUtilities.broadcast(ChatColor.RED + "restart.");
for (Player p : Bukkit.getOnlinePlayers()) p.playSound(p.getLocation(), Sound.ENDERDRAGON_WINGS, 5, 1);
return;
}
Game.start();
}
boolean broadcast;
for (Player p : Bukkit.getOnlinePlayers()) {
p.setLevel(timeUntilStart);
if (timeUntilStart < 11 || timeUntilStart == 60 || timeUntilStart == 30) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 0);
if (timeUntilStart == 1) p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 1);
broadcast = true;
}
}
if (broadcast) ChatUtilities.broadcast(String.valueOf(timeUntilStart) + " §6Seconds until the game starts!");
timeUntilStart -= 1;
}
as Tanner Little said above
You are broadcasting for every player that is online. You need to move any code that you don't want to run for every player outside of the for loop.
You need to make sure as well that you are cancelling the task. I would recommend using the inbuilt scheduler. You can access the scheduler in this way
private int countDownTimer
private int countDownTime
public void runCountDown() {
countDownTimer = Bukkit.getScheduler.scheduleSyncDelayedTask(plugin, new runnable() {
public void run {
if (countDownTime <= 0) {
//do your bradcasting here
for (Player ingame : Bukkit.getOnlinePlayers()) {
//Do your player specific stuff here
}
Bukkit.getScheduler.cancelTask(countDownTimer);
}
if (countDownTime % 10 == 0) { //You can pick whaterver times u want this is just for an example
//Do periodic broadcasting
}
countDownTime -= 1;
}
}, 0L, 20L); //This means that it would wait 0 ticks to start the countdown and do the task every 20 ticks ie) 1 second.
}
Hopefully this helps you.
I'm sure you've been there. You want to say "if flib do this, if flob do that, if flab do diet, etc" where any number of them can be true, then at the end you want an "if you didn't do ANY of them".
For example (the examples below are in Swift, as I've been playing with it, but I think the situation is the same in most languages):
let thing = 101
var isInteresting = false
if (thing % 3 == 0) {
println("\"\(thing)\" is a multiple of three.")
isInteresting = true
}
if (thing > 100) {
println("\"\(thing)\" is greater than one hundred.")
isInteresting = true
}
if (thing > 1000) {
println("\"\(thing)\" is greater than one thousand.")
isInteresting = true
}
if !isInteresting {
println("\"\(thing)\" is boring.")
}
I find keeping track of a boolean to tell me whether I did anything or not kinda ungainly.
The only other way I came up with was this:
let thing = 101
let isAMultipleOfThree = (thing % 3 == 0)
let isGreaterThan100 = (thing > 100)
let isGreaterThan1000 = (thing > 1000)
if isAMultipleOfThree {
println("\"\(thing)\" is a multiple of three.")
}
if isGreaterThan100 {
println("\"\(thing)\" is greater than one hundred.")
}
if isGreaterThan1000 {
println("\"\(thing)\" is greater than one thousand.")
}
if !(isAMultipleOfThree || isGreaterThan100 || isGreaterThan1000 ) {
println("\"\(thing)\" is boring.")
}
but if anything that's worse (if you add a new clause you need to remember to add it in three places.
So my question is, is there a neat, succinct way of doing this?
I'm dreaming of an imaginary switch-like statement:
switchif { //Would have fallthrough where every case condition is checked
case thing % 3 == 0:
println("\"\(thing)\" is a multiple of three.")
case thing >100 :
println("\"\(thing)\" is greater than one hundred.")
case thing > 1000:
println("\"\(thing)\" is greater than one thousand.")
none: //Unlike 'default' this would only occur if none of the above did
println("\"\(thing)\" is boring.")
}
It's a good question that does not have a perfect answer. However, here's one other idea in addition to those you suggest: Encapsulate the testing machinery in a procedure to allow the calling code at least to be a bit more streamlined.
Specifically, for your example, the calling code can be this:
if (! doInterestingStuff(101)) {
println("\"\(thing)\" is boring.");
}
If testing is encapsulated into a procedure:
public boolean doInterestingStuff(int thing) {
var isInteresting = false
if (thing % 3 == 0) {
println("\"\(thing)\" is a multiple of three.")
isInteresting = true
}
if (thing > 100) {
println("\"\(thing)\" is greater than one hundred.")
isInteresting = true
}
if (thing > 1000) {
println("\"\(thing)\" is greater than one thousand.")
isInteresting = true
}
return isInteresting
}
I'm not sure how you'd do this in Swift, but since you didn't give a language tag I'll answer in C++.
The key to this is that && is short circuiting, and the second part won't be evaluated when the first part is false. It's the same idea as your boolean flag, but it's a little more automated.
struct Tracker
{
Tracker() : any(false) { }
bool operator()() { any = true; return true; }
bool any;
};
int thing = 101;
Tracker tracker;
if (thing % 3 == 0 && tracker()) {
printf("\"%d\" is a multiple of three.\n", thing);
}
if (thing > 100 && tracker()) {
printf("\"%d\" is greater than one hundred.\n", thing);
}
if (thing > 1000 && tracker()) {
printf("\"%d\" is greater than one thousand.\n", thing);
}
if (!tracker.any) {
printf("\"%d\" is boring.\n", thing);
}
See it in action: http://ideone.com/6MQYY2
kjhughes' answer inspired me a little:
Perhaps one could write a global function that accepts an indeterminate number of key-value pairs (or even just two element arrays), where the key is a comparison and the value is the statement to run if it's true. Then return false if none of them were run, otherwise true.
Update:
Tried it, it's horrible!
//Function:
func ifNone(ifNoneFunc:()->Void, tests: Bool...)
{
var oneTestPassed = false
for test in tests
{
oneTestPassed |= test
}
if(!oneTestPassed)
{
ifNoneFunc()
}
}
//Example:
let thisThing = 7
ifNone(
{
println("\(thisThing) is boring")
},
{
if(thisThing % 10 == 0)
{
println("\"\(thisThing)\" is a multiple of 10")
return true
}
else
{
return false
}
}(),
{
if(thisThing % 3 == 0)
{
println("\"\(thisThing)\" is a multiple of 3")
return true
}
else
{
return false
}
}(),
{
if(thisThing > 1_000_000)
{
println("\"\(thisThing)\" is over a million!!")
return true
}
else
{
return false
}
}()
)
I'm trying to upgrade the FFMpeg source used with one of our projects but get_buffer has gone away. I'm not 100% sure on which method to replace it with. Here are two contexts in which its used, any help is appreciated.
I look forward to hearing from you soon,
Thanks,
Kevin
cur_offset = avio_tell(pb);
if (!para->playctrl_info.read_end_flag && (0 == pkt->data_size)) {
rev_byte = get_buffer(pb, pbuf, para->max_raw_size);
if ((rev_byte > 0) && (cur_offset <= para->pFormatCtx->data_offset)) {
try_count = 0;
pkt->data_size = rev_byte;
para->read_size.total_bytes += rev_byte;
pkt->avpkt_newflag = 1;
pkt->avpkt_isvalid = 1;
do {
read_length = get_buffer(s->pb, data + 12, read_size);
if ((read_length <= 0) || (sync_flag == 1024)) {
if (read_length == AVERROR(EAGAIN)) {
continue;
} else {
FREE(data);
log_error("[%s]get data failed. ret=%d\n", __FUNCTION__, read_length);
return 0;
}
} else {
break;
}
} while (retry_get_data < am_p->playctrl_info.read_max_retry_cnt);
pkt = data;
Although you already found your answer I will provide an answer in case others have the same issue. durandal_1707 provided the answer to you (I assume) in #ffmpeg-devel IRC:
expresspotato: I'm having trouble integrating the latest version of
ffmpeg against an old one from about a year and a half ago. It appears
get_buffer defined in aviobuf.c has gone away. Do you know which
method I should replace it with?
durandal_1707: in e63a362857d9807b23e65872598d782fa53bb6af get_buffer
have been renamed to avio_read